Compare commits
111 Commits
8f684f4169
...
d2ca303c5e
Author | SHA1 | Date |
---|---|---|
Wilson E. Alvarez | d2ca303c5e | |
Wilson E. Alvarez | fe597a5a46 | |
Wilson E. Alvarez | d20d28be78 | |
Wilson E. Alvarez | 2f1fd6fb62 | |
Wilson E. Alvarez | 022d95434d | |
Wilson E. Alvarez | ce28ed92d2 | |
Wilson E. Alvarez | 8f294ac5ea | |
Wilson E. Alvarez | 9410031d45 | |
Serhii Snitsaruk | 61b2db5a07 | |
Serhii Snitsaruk | 15464e288c | |
Serhii Snitsaruk | 4467ebbbd9 | |
Serhii Snitsaruk | a2dedabd77 | |
Serhii Snitsaruk | 2356e6c967 | |
Serhii Snitsaruk | b712fe25dc | |
Serhii Snitsaruk | 5bdec804b3 | |
Serhii Snitsaruk | 2784937ca8 | |
Serhii Snitsaruk | d383e9d1a4 | |
Serhii Snitsaruk | 4f1b22c668 | |
Serhii Snitsaruk | 8fa609ef9e | |
Serhii Snitsaruk | c6851259e8 | |
Serhii Snitsaruk | 5a60ad9308 | |
Serhii Snitsaruk | 7a90fdb113 | |
Serhii Snitsaruk | 3bc8343e8b | |
Serhii Snitsaruk | 1c7eb994d4 | |
Serhii Snitsaruk | c76278b735 | |
Serhii Snitsaruk | fc53078130 | |
Serhii Snitsaruk | 88583a8a2e | |
Serhii Snitsaruk | d6076d131f | |
Serhii Snitsaruk | 2d1c5fa4ba | |
Serhii Snitsaruk | 7eaebc4e7c | |
Serhii Snitsaruk | db73133f1b | |
Serhii Snitsaruk | 7c0c81d141 | |
Serhii Snitsaruk | adff6bd08c | |
Serhii Snitsaruk | 06de52492a | |
Serhii Snitsaruk | 2c8e0d2da0 | |
Serhii Snitsaruk | ce5f012101 | |
Serhii Snitsaruk | 3bca05bc50 | |
Serhii Snitsaruk | 56bb91df0a | |
Serhii Snitsaruk | c793c8ba53 | |
Serhii Snitsaruk | 808ca1de7f | |
Serhii Snitsaruk | 809efc1be2 | |
Serhii Snitsaruk | 29532113c0 | |
Serhii Snitsaruk | 1e6c3fa92b | |
Serhii Snitsaruk | 35f2c3c142 | |
Serhii Snitsaruk | 49f5e3be79 | |
Serhii Snitsaruk | a04d4aaca4 | |
Serhii Snitsaruk | 08ad6c1d99 | |
Serhii Snitsaruk | c9825413c0 | |
Serhii Snitsaruk | 990438db55 | |
Serhii Snitsaruk | 2b299c0007 | |
Serhii Snitsaruk | 88e468c526 | |
Serhii Snitsaruk | a0cd983927 | |
Serhii Snitsaruk | 792502db84 | |
Serhii Snitsaruk | 5f5ecc2db1 | |
Serhii Snitsaruk | 361eb3eb15 | |
Serhii Snitsaruk | dbb89e6883 | |
Serhii Snitsaruk | fa3034d190 | |
Serhii Snitsaruk | 9e0489a034 | |
Serhii Snitsaruk | a7d4b1e7f7 | |
Serhii Snitsaruk | 127fa678f4 | |
Serhii Snitsaruk | e0d47ddf08 | |
Serhii Snitsaruk | 57382e10a7 | |
Serhii Snitsaruk | 0a28feb7a9 | |
Serhii Snitsaruk | 6f8f95b5de | |
Serhii Snitsaruk | e9eec23c3e | |
Serhii Snitsaruk | d0fcea5574 | |
Serhii Snitsaruk | e059429760 | |
Serhii Snitsaruk | 918095622c | |
Serhii Snitsaruk | 23c19c11e6 | |
Serhii Snitsaruk | bc2c4a26ac | |
Serhii Snitsaruk | 83214fc93b | |
Serhii Snitsaruk | e062669cf7 | |
Serhii Snitsaruk | 2e94bf8bf2 | |
Serhii Snitsaruk | e8816091e6 | |
Serhii Snitsaruk | fc1b99a5b1 | |
Serhii Snitsaruk | 04300e5222 | |
Serhii Snitsaruk | 2f326e5b6f | |
Serhii Snitsaruk | 064d00fdfa | |
Serhii Snitsaruk | ff61d55c44 | |
Serhii Snitsaruk | 7ab7a9d098 | |
Serhii Snitsaruk | b54f3696ff | |
Serhii Snitsaruk | dc77ecd2b2 | |
Serhii Snitsaruk | 026272f7f7 | |
Serhii Snitsaruk | d08018b7b1 | |
Serhii Snitsaruk | 00396dce61 | |
Serhii Snitsaruk | 69201fa877 | |
Serhii Snitsaruk | d920060dee | |
Serhii Snitsaruk | 2718271bb1 | |
Serhii Snitsaruk | 3cf90f9387 | |
Serhii Snitsaruk | c6b1a40627 | |
Serhii Snitsaruk | d36f8f1122 | |
Serhii Snitsaruk | a572613001 | |
Serhii Snitsaruk | c30c5a4d7a | |
Serhii Snitsaruk | ef1c1e5192 | |
Serhii Snitsaruk | 3b12288ae0 | |
Serhii Snitsaruk | a1cdff2e2e | |
Serhii Snitsaruk | e43bc25d82 | |
Ola S. | 549d73b8fc | |
Serhii Snitsaruk | 0d1e846d93 | |
Serhii Snitsaruk | 2d493a76bd | |
Serhii Snitsaruk | bdfe5f52c2 | |
Serhii Snitsaruk | e55611a1a9 | |
Serhii Snitsaruk | ba467ad62c | |
Serhii Snitsaruk | e5d04b9eda | |
Serhii Snitsaruk | e36ea6d3e6 | |
Serhii Snitsaruk | 803da63fa8 | |
Serhii Snitsaruk | 84c89356a6 | |
Serhii Snitsaruk | a2dae24b99 | |
Serhii Snitsaruk | af23272e3d | |
Serhii Snitsaruk | 506d8aa967 | |
Serhii Snitsaruk | 5dff2e537b |
|
@ -0,0 +1,64 @@
|
||||||
|
name: Bug report
|
||||||
|
description: Report a bug in LimboAI
|
||||||
|
labels:
|
||||||
|
- bug
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
- Write a descriptive title above.
|
||||||
|
- Search [open](https://github.com/limbonaut/limboai/issues) and [closed](https://github.com/limbonaut/limboai/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Godot version
|
||||||
|
description: |
|
||||||
|
- Specify the Godot version and hardware information if relevant.
|
||||||
|
- You can copy the version info by clicking on it in the Godot status bar.
|
||||||
|
- Alternatively, you can copy the version and hardware info in Godot using the main menu command "Help -> Copy System Info".
|
||||||
|
placeholder: v4.2.2.limboai+v1.1.0.gha [15073afe3]
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: LimboAI version
|
||||||
|
description: |
|
||||||
|
- Specify the LimboAI version.
|
||||||
|
- You can copy the version info by clicking on it in the toolbar of the LimboAI editor (top-right corner).
|
||||||
|
placeholder: v1.1.0 [8fa609e]
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: variant
|
||||||
|
attributes:
|
||||||
|
label: LimboAI variant
|
||||||
|
description: Which variant of our plugin are you running?
|
||||||
|
options:
|
||||||
|
- GDExtension / AssetLib
|
||||||
|
- Module (custom editor or template build)
|
||||||
|
default: 0
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Issue description
|
||||||
|
description: |
|
||||||
|
- Describe your issue in detail. What doesn't work and how do you expect it to work instead?
|
||||||
|
- Provide screenshots and/or a console output if it helps to convey the problem.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: How to reproduce
|
||||||
|
description: |
|
||||||
|
- Provide a list of steps or sample code that reproduces the issue.
|
||||||
|
- You can provide a small Godot project which reproduces the issue, with no unnecessary files included.
|
||||||
|
- Drag and drop a ZIP archive to upload it (10Mb limit).
|
||||||
|
- Don't include the `.godot` folder in the archive.
|
||||||
|
- Redroduction project helps to find the bug more quickly!
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -0,0 +1,14 @@
|
||||||
|
blank_issues_enabled: false
|
||||||
|
|
||||||
|
contact_links:
|
||||||
|
- name: Documentation
|
||||||
|
url: https://limboai.readthedocs.io/en/stable/
|
||||||
|
about: Please see our documentation for more information.
|
||||||
|
|
||||||
|
- name: Discussions
|
||||||
|
url: https://github.com/limbonaut/limboai/discussions
|
||||||
|
about: Need help? Ask questions in Discussions or on our Discord server.
|
||||||
|
|
||||||
|
- name: Discord Server
|
||||||
|
url: https://discord.gg/N5MGC95GpP
|
||||||
|
about: Share your experience or get help on our Discord server.
|
|
@ -0,0 +1,38 @@
|
||||||
|
name: Feature or improvement proposal
|
||||||
|
description: Propose a new feature to be added or improved in LimboAI
|
||||||
|
labels:
|
||||||
|
- enhancement
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
- Write a descriptive title above.
|
||||||
|
- Search [open](https://github.com/limbonaut/limboai/issues) and [closed](https://github.com/limbonaut/limboai/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Problem statement
|
||||||
|
description: |
|
||||||
|
- Describe the problem or limitation you're currently facing with the LimboAI plugin.
|
||||||
|
- If it helps, describe the project you're working on and how it relates to the problem or limitation.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Proposed solution
|
||||||
|
description: |
|
||||||
|
- Describe your proposed solution and how it helps to overcome the problem or limitation.
|
||||||
|
- If it helps, show how it will work with code, pseudo-code, mock-ups, and/or diagrams.
|
||||||
|
- You can include any images or videos with drag'n'drop, and sample code blocks with <code>```</code> tags.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Alternatives
|
||||||
|
description: |
|
||||||
|
- Describe alternative solutions and features you've considered.
|
||||||
|
- If this enhancement will not be used often, can it be worked around with a few clicks or lines of code?
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: Setup Linux toolchain
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
arch:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Set up environment
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# ! Settings:
|
||||||
|
TOOLCHAIN_64_URL=https://github.com/godotengine/buildroot/releases/download/godot-2020.11.x-2/x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
||||||
|
TOOLCHAIN_64_SHA=16c8302fcb676c1f0fb9df73d6cff250ba1f4286
|
||||||
|
TOOLCHAIN_32_URL=https://github.com/godotengine/buildroot/releases/download/godot-2020.11.x-2/i686-godot-linux-gnu_sdk-buildroot.tar.bz2
|
||||||
|
TOOLCHAIN_32_SHA=6171652abc54ef219e5187bc53660ee4e2f796f4
|
||||||
|
# ! Export variables:
|
||||||
|
if [[ "${{ inputs.arch }}" == "x86_64" ]]; then
|
||||||
|
echo "TOOLCHAIN_URL=${TOOLCHAIN_64_URL}" >> "$GITHUB_ENV"
|
||||||
|
echo "TOOLCHAIN_SHA=${TOOLCHAIN_64_SHA}" >> "$GITHUB_ENV"
|
||||||
|
elif [[ "${{ inputs.arch }}" == "x86_32" ]]; then
|
||||||
|
echo "TOOLCHAIN_URL=${TOOLCHAIN_32_URL}" >> "$GITHUB_ENV"
|
||||||
|
echo "TOOLCHAIN_SHA=${TOOLCHAIN_32_SHA}" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Cache buildroot
|
||||||
|
id: cache-buildroot
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: buildroot
|
||||||
|
key: ${{env.TOOLCHAIN_SHA}}
|
||||||
|
|
||||||
|
- name: Set up buildroot
|
||||||
|
if: steps.cache-buildroot.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir buildroot
|
||||||
|
wget ${TOOLCHAIN_URL} -O buildroot/buildroot.tar.bz2
|
||||||
|
cd buildroot
|
||||||
|
echo "${TOOLCHAIN_SHA} buildroot.tar.bz2"
|
||||||
|
echo "${TOOLCHAIN_SHA} buildroot.tar.bz2" | shasum --check
|
||||||
|
tar -xjf buildroot.tar.bz2 --strip-components=1
|
||||||
|
ls -l
|
||||||
|
rm buildroot.tar.bz2
|
||||||
|
./relocate-sdk.sh
|
||||||
|
cd ..
|
|
@ -36,6 +36,7 @@ env:
|
||||||
SCONSFLAGS: dev_build=no debug_symbols=no
|
SCONSFLAGS: dev_build=no debug_symbols=no
|
||||||
EM_VERSION: 3.1.45
|
EM_VERSION: 3.1.45
|
||||||
EM_CACHE_FOLDER: "emsdk-cache"
|
EM_CACHE_FOLDER: "emsdk-cache"
|
||||||
|
GODOT_VERSION: 4.2-stable
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
gdextension:
|
gdextension:
|
||||||
|
@ -94,14 +95,70 @@ jobs:
|
||||||
platform: web
|
platform: web
|
||||||
target: template_release
|
target: template_release
|
||||||
arch: wasm32
|
arch: wasm32
|
||||||
should-build: true
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
- name: 🌐 Web (wasm32, debug)
|
- name: 🌐 Web (wasm32, debug)
|
||||||
runner: ubuntu-20.04
|
runner: ubuntu-20.04
|
||||||
platform: web
|
platform: web
|
||||||
target: template_debug
|
target: template_debug
|
||||||
arch: wasm32
|
arch: wasm32
|
||||||
should-build: true
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (arm64, release)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_release
|
||||||
|
arch: arm64
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (arm64, debug)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_debug
|
||||||
|
arch: arm64
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (arm32, release)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_release
|
||||||
|
arch: arm32
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (arm32, debug)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_debug
|
||||||
|
arch: arm32
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (x86_64, release)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_release
|
||||||
|
arch: x86_64
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (x86_64, debug)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_debug
|
||||||
|
arch: x86_64
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (x86_32, release)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_release
|
||||||
|
arch: x86_32
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
|
- name: 🤖 Android (x86_32, debug)
|
||||||
|
runner: ubuntu-20.04
|
||||||
|
platform: android
|
||||||
|
target: template_debug
|
||||||
|
arch: x86_32
|
||||||
|
should-build: ${{ !inputs.test-build }}
|
||||||
|
|
||||||
exclude:
|
exclude:
|
||||||
- { opts: { should-build: false } }
|
- { opts: { should-build: false } }
|
||||||
|
@ -132,25 +189,11 @@ jobs:
|
||||||
id: output-name-prefix
|
id: output-name-prefix
|
||||||
run: echo "name-prefix=${NAME_PREFIX}" >> $GITHUB_OUTPUT
|
run: echo "name-prefix=${NAME_PREFIX}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Linux buildroot x86_64
|
- name: Setup Linux toolchain
|
||||||
if: matrix.opts.platform == 'linux' && matrix.opts.arch == 'x86_64'
|
if: matrix.opts.platform == 'linux'
|
||||||
run: |
|
uses: ./limboai/.github/actions/setup-linux-toolchain
|
||||||
wget https://download.tuxfamily.org/godotengine/toolchains/linux/x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
with:
|
||||||
tar -xjf x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
arch: ${{matrix.opts.arch}}
|
||||||
mv x86_64-godot-linux-gnu_sdk-buildroot buildroot
|
|
||||||
cd buildroot
|
|
||||||
./relocate-sdk.sh
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
- name: Set up Linux buildroot x86_32
|
|
||||||
if: matrix.opts.platform == 'linux' && matrix.opts.arch == 'x86_32'
|
|
||||||
run: |
|
|
||||||
wget https://download.tuxfamily.org/godotengine/toolchains/linux/i686-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
tar -xjf i686-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
mv i686-godot-linux-gnu_sdk-buildroot buildroot
|
|
||||||
cd buildroot
|
|
||||||
./relocate-sdk.sh
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
- name: Set up Python 3.x
|
- name: Set up Python 3.x
|
||||||
if: matrix.opts.platform == 'windows' || matrix.opts.platform == 'macos'
|
if: matrix.opts.platform == 'windows' || matrix.opts.platform == 'macos'
|
||||||
|
@ -179,13 +222,27 @@ jobs:
|
||||||
emcc -v
|
emcc -v
|
||||||
|
|
||||||
- name: Set up scons
|
- name: Set up scons
|
||||||
if: matrix.opts.platform == 'windows' || matrix.opts.platform == 'macos' || matrix.opts.platform == 'web'
|
if: matrix.opts.platform != 'linux'
|
||||||
run: |
|
run: |
|
||||||
python -c "import sys; print(sys.version)"
|
python -c "import sys; print(sys.version)"
|
||||||
python -m pip install scons==4.4.0
|
python -m pip install scons==4.4.0
|
||||||
python --version
|
python --version
|
||||||
scons --version
|
scons --version
|
||||||
|
|
||||||
|
- name: Set up Java 17
|
||||||
|
if: matrix.opts.platform == 'android'
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- uses: nttld/setup-ndk@v1
|
||||||
|
if: matrix.opts.platform == 'android'
|
||||||
|
id: setup-ndk
|
||||||
|
with:
|
||||||
|
ndk-version: r23c
|
||||||
|
link-to-sdk: true
|
||||||
|
|
||||||
- name: Set up MSVC problem matcher on Windows
|
- name: Set up MSVC problem matcher on Windows
|
||||||
if: matrix.opts.platform == 'windows'
|
if: matrix.opts.platform == 'windows'
|
||||||
uses: ammaraskar/msvc-problem-matcher@master
|
uses: ammaraskar/msvc-problem-matcher@master
|
||||||
|
@ -231,7 +288,7 @@ jobs:
|
||||||
ls -R out/
|
ls -R out/
|
||||||
|
|
||||||
- name: Strip lib
|
- name: Strip lib
|
||||||
if: matrix.opts.platform != 'windows' && matrix.opts.platform != 'web'
|
if: matrix.opts.platform != 'windows' && matrix.opts.platform != 'web' && (matrix.opts.platform != 'android' || startsWith(matrix.opts.arch, 'x86'))
|
||||||
run: |
|
run: |
|
||||||
ls -l -R out/addons/limboai/bin/
|
ls -l -R out/addons/limboai/bin/
|
||||||
echo "---"
|
echo "---"
|
||||||
|
@ -251,8 +308,8 @@ jobs:
|
||||||
name: ${{ env.NAME }}
|
name: ${{ env.NAME }}
|
||||||
path: out/*
|
path: out/*
|
||||||
|
|
||||||
merge-artifacts:
|
package-extension:
|
||||||
name: Merge artifacts
|
name: 📦 Package extension
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: gdextension
|
needs: gdextension
|
||||||
|
|
||||||
|
@ -263,3 +320,48 @@ jobs:
|
||||||
name: ${{needs.gdextension.outputs.name-prefix}}
|
name: ${{needs.gdextension.outputs.name-prefix}}
|
||||||
pattern: tmp-gdextension.*
|
pattern: tmp-gdextension.*
|
||||||
delete-merged: true
|
delete-merged: true
|
||||||
|
|
||||||
|
- name: Download artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{needs.gdextension.outputs.name-prefix}}
|
||||||
|
path: out/
|
||||||
|
|
||||||
|
- name: Setup Godot
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Downloading Godot ${GODOT_VERSION}"
|
||||||
|
mkdir bin
|
||||||
|
cd bin
|
||||||
|
wget "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_linux.x86_64.zip" -O godot.zip
|
||||||
|
unzip godot.zip
|
||||||
|
rm godot.zip
|
||||||
|
mv Godot_* godot
|
||||||
|
chmod u+x godot
|
||||||
|
ls -l
|
||||||
|
cd ..
|
||||||
|
./bin/godot --version
|
||||||
|
|
||||||
|
- name: Generate icon .import files
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
touch out/project.godot
|
||||||
|
timeout 20s ./bin/godot --headless --editor --path ./out/ || /bin/true
|
||||||
|
rm out/project.godot
|
||||||
|
rm -rf out/.godot/
|
||||||
|
|
||||||
|
- name: Change editor icon import settings
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "--- Listing icons dir:"
|
||||||
|
ls out/addons/limboai/icons/
|
||||||
|
echo "--- (end of listing)"
|
||||||
|
sed -i 's|editor/scale_with_editor_scale=false|editor/scale_with_editor_scale=true|' out/addons/limboai/icons/*.import
|
||||||
|
sed -i 's|editor/convert_colors_with_editor_theme=false|editor/convert_colors_with_editor_theme=true|' out/addons/limboai/icons/*.import
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{needs.gdextension.outputs.name-prefix}}
|
||||||
|
path: out/*
|
||||||
|
overwrite: true
|
||||||
|
|
|
@ -139,27 +139,10 @@ jobs:
|
||||||
# Inits GODOT_VERSION, LIMBOAI_VERSION and NAME_PREFIX environment variables.
|
# Inits GODOT_VERSION, LIMBOAI_VERSION and NAME_PREFIX environment variables.
|
||||||
- uses: ./modules/limboai/.github/actions/init-version
|
- uses: ./modules/limboai/.github/actions/init-version
|
||||||
|
|
||||||
# About sed see: https://github.com/godotengine/buildroot/issues/6
|
- name: Set up Linux toolchain
|
||||||
- name: Set up buildroot x86_64
|
uses: ./modules/limboai/.github/actions/setup-linux-toolchain
|
||||||
if: matrix.opts.arch == 'x86_64'
|
with:
|
||||||
run: |
|
arch: ${{matrix.opts.arch}}
|
||||||
wget https://download.tuxfamily.org/godotengine/toolchains/linux/x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
tar -xjf x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
mv x86_64-godot-linux-gnu_sdk-buildroot buildroot
|
|
||||||
cd buildroot
|
|
||||||
sed -i x86_64-godot-linux-gnu/sysroot/usr/lib/pkgconfig/dbus-1.pc -e "s@/lib@/lib64@g"
|
|
||||||
./relocate-sdk.sh
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
- name: Set up buildroot x86_32
|
|
||||||
if: matrix.opts.arch == 'x86_32'
|
|
||||||
run: |
|
|
||||||
wget https://download.tuxfamily.org/godotengine/toolchains/linux/i686-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
tar -xjf i686-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
mv i686-godot-linux-gnu_sdk-buildroot buildroot
|
|
||||||
cd buildroot
|
|
||||||
./relocate-sdk.sh
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
- name: Set up scons cache
|
- name: Set up scons cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
|
|
|
@ -26,8 +26,8 @@ concurrency:
|
||||||
|
|
||||||
# Global Settings.
|
# Global Settings.
|
||||||
env:
|
env:
|
||||||
GODOT_REF: "4.2"
|
GODOT_REF: "master"
|
||||||
GODOT_CPP_REF: "4.2"
|
GODOT_CPP_REF: "master"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
unit-tests:
|
unit-tests:
|
||||||
|
@ -52,16 +52,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
path: modules/limboai
|
path: modules/limboai
|
||||||
|
|
||||||
# About sed see: https://github.com/godotengine/buildroot/issues/6
|
- name: Set up Linux toolchain
|
||||||
- name: Set up buildroot x86_64
|
uses: ./modules/limboai/.github/actions/setup-linux-toolchain
|
||||||
run: |
|
with:
|
||||||
wget https://download.tuxfamily.org/godotengine/toolchains/linux/x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
arch: x86_64
|
||||||
tar -xjf x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
|
|
||||||
mv x86_64-godot-linux-gnu_sdk-buildroot buildroot
|
|
||||||
cd buildroot
|
|
||||||
sed -i x86_64-godot-linux-gnu/sysroot/usr/lib/pkgconfig/dbus-1.pc -e "s@/lib@/lib64@g"
|
|
||||||
./relocate-sdk.sh
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
- name: Set up scons cache
|
- name: Set up scons cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
|
|
28
README.md
28
README.md
|
@ -29,13 +29,14 @@ Behavior Trees are powerful hierarchical structures used to model and control th
|
||||||
|
|
||||||
![Charger from Demo](doc/images/demo_charger.gif)
|
![Charger from Demo](doc/images/demo_charger.gif)
|
||||||
|
|
||||||
### Videos
|
|
||||||
|
|
||||||
[![Demonstration](https://img.youtube.com/vi/NWaMArUg7mY/0.jpg)](https://www.youtube.com/watch?v=NWaMArUg7mY)
|
|
||||||
|
|
||||||
>**🛈 Demo project** lives in the `demo` folder and is available separately in [**Releases**](https://github.com/limbonaut/limboai/releases).
|
>**🛈 Demo project** lives in the `demo` folder and is available separately in [**Releases**](https://github.com/limbonaut/limboai/releases).
|
||||||
> Run `demo/scenes/showcase.tscn` to get started.
|
> Run `demo/scenes/showcase.tscn` to get started.
|
||||||
> It also contains a tutorial that introduces behavior trees using examples.
|
> It also includes a tutorial that introduces behavior trees through illustrative examples.
|
||||||
|
|
||||||
|
### Videos
|
||||||
|
|
||||||
|
<a href="https://www.youtube.com/watch?v=NWaMArUg7mY"><img src="https://img.youtube.com/vi/NWaMArUg7mY/0.jpg" width=410></a>
|
||||||
|
<a href="https://www.youtube.com/watch?v=aP0Aacdxmno"><img src="https://img.youtube.com/vi/aP0Aacdxmno/0.jpg" width=410></a>
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
@ -72,6 +73,10 @@ Behavior Trees are powerful hierarchical structures used to model and control th
|
||||||
|
|
||||||
- **Demo + Tutorial:** Check out our extensive demo project, which includes an introduction to behavior trees using examples.
|
- **Demo + Tutorial:** Check out our extensive demo project, which includes an introduction to behavior trees using examples.
|
||||||
|
|
||||||
|
## First steps
|
||||||
|
|
||||||
|
Follow the [First steps](https://limboai.readthedocs.io/en/latest/index.html#first-steps) guide to learn how to get started with LimboAI and the demo project.
|
||||||
|
|
||||||
## Getting LimboAI
|
## Getting LimboAI
|
||||||
|
|
||||||
LimboAI can be used as either a C++ module or as a GDExtension shared library. GDExtension version is more convenient to use but somewhat limited in features. Whichever you choose to use, your project will stay compatible with both and you can switch from one to the other any time. See [Using GDExtension](https://limboai.readthedocs.io/en/latest/getting-started/gdextension.html).
|
LimboAI can be used as either a C++ module or as a GDExtension shared library. GDExtension version is more convenient to use but somewhat limited in features. Whichever you choose to use, your project will stay compatible with both and you can switch from one to the other any time. See [Using GDExtension](https://limboai.readthedocs.io/en/latest/getting-started/gdextension.html).
|
||||||
|
@ -93,6 +98,7 @@ LimboAI can be used as either a C++ module or as a GDExtension shared library. G
|
||||||
## Using the plugin
|
## Using the plugin
|
||||||
|
|
||||||
- [Online Documentation](https://limboai.readthedocs.io/en/latest/index.html)
|
- [Online Documentation](https://limboai.readthedocs.io/en/latest/index.html)
|
||||||
|
- [First steps](https://limboai.readthedocs.io/en/latest/index.html#first-steps)
|
||||||
- [Introduction to Behavior Trees](https://limboai.readthedocs.io/en/latest/getting-started/introduction.html)
|
- [Introduction to Behavior Trees](https://limboai.readthedocs.io/en/latest/getting-started/introduction.html)
|
||||||
- [Creating custom tasks in GDScript](https://limboai.readthedocs.io/en/latest/getting-started/custom-tasks.html)
|
- [Creating custom tasks in GDScript](https://limboai.readthedocs.io/en/latest/getting-started/custom-tasks.html)
|
||||||
- [Sharing data using Blackboard](https://limboai.readthedocs.io/en/latest/getting-started/using-blackboard.html)
|
- [Sharing data using Blackboard](https://limboai.readthedocs.io/en/latest/getting-started/using-blackboard.html)
|
||||||
|
@ -114,18 +120,6 @@ Need help? We have a Discord server: https://discord.gg/N5MGC95GpP
|
||||||
|
|
||||||
I write about LimboAI development on Mastodon: https://mastodon.gamedev.place/@limbo.
|
I write about LimboAI development on Mastodon: https://mastodon.gamedev.place/@limbo.
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
Features and improvements that may be implemented in the future:
|
|
||||||
- ~~Providing precompiled builds for download.~~ 🗸
|
|
||||||
- ~~Tests and CI.~~ 🗸
|
|
||||||
- ~~GDExtension support.~~ 🗸
|
|
||||||
- ~~Extensive demo project.~~ 🗸
|
|
||||||
- Expanding the library of commonly useful tasks.
|
|
||||||
- Exploring the execution history of behavior trees in the visual debugger.
|
|
||||||
- Per-project ignore list for tasks that users may want to hide in the task palette.
|
|
||||||
- GUI editor for state machines.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Use of this source code is governed by an MIT-style license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
Use of this source code is governed by an MIT-style license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
||||||
|
|
4
SCsub
4
SCsub
|
@ -7,6 +7,10 @@ module_env = env.Clone()
|
||||||
|
|
||||||
module_env.Append(CPPDEFINES=["LIMBOAI_MODULE"])
|
module_env.Append(CPPDEFINES=["LIMBOAI_MODULE"])
|
||||||
|
|
||||||
|
import limboai_version
|
||||||
|
|
||||||
|
limboai_version.generate_module_version_header()
|
||||||
|
|
||||||
module_env.add_source_files(env.modules_sources, "*.cpp")
|
module_env.add_source_files(env.modules_sources, "*.cpp")
|
||||||
module_env.add_source_files(env.modules_sources, "blackboard/*.cpp")
|
module_env.add_source_files(env.modules_sources, "blackboard/*.cpp")
|
||||||
module_env.add_source_files(env.modules_sources, "blackboard/bb_param/*.cpp")
|
module_env.add_source_files(env.modules_sources, "blackboard/bb_param/*.cpp")
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBAabb : public BBParam {
|
||||||
GDCLASS(BBAabb, BBParam);
|
GDCLASS(BBAabb, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::AABB; }
|
virtual Variant::Type get_type() const override { return Variant::AABB; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBArray : public BBParam {
|
||||||
GDCLASS(BBArray, BBParam);
|
GDCLASS(BBArray, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBBasis : public BBParam {
|
||||||
GDCLASS(BBBasis, BBParam);
|
GDCLASS(BBBasis, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::BASIS; }
|
virtual Variant::Type get_type() const override { return Variant::BASIS; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBBool : public BBParam {
|
||||||
GDCLASS(BBBool, BBParam);
|
GDCLASS(BBBool, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::BOOL; }
|
virtual Variant::Type get_type() const override { return Variant::BOOL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBByteArray : public BBParam {
|
||||||
GDCLASS(BBByteArray, BBParam);
|
GDCLASS(BBByteArray, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_BYTE_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_BYTE_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBColor : public BBParam {
|
||||||
GDCLASS(BBColor, BBParam);
|
GDCLASS(BBColor, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::COLOR; }
|
virtual Variant::Type get_type() const override { return Variant::COLOR; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBColorArray : public BBParam {
|
||||||
GDCLASS(BBColorArray, BBParam);
|
GDCLASS(BBColorArray, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_COLOR_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_COLOR_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBDictionary : public BBParam {
|
||||||
GDCLASS(BBDictionary, BBParam);
|
GDCLASS(BBDictionary, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::DICTIONARY; }
|
virtual Variant::Type get_type() const override { return Variant::DICTIONARY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBFloat : public BBParam {
|
||||||
GDCLASS(BBFloat, BBParam);
|
GDCLASS(BBFloat, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::FLOAT; }
|
virtual Variant::Type get_type() const override { return Variant::FLOAT; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBFloat32Array : public BBParam {
|
||||||
GDCLASS(BBFloat32Array, BBParam);
|
GDCLASS(BBFloat32Array, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_FLOAT32_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_FLOAT32_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBFloat64Array : public BBParam {
|
||||||
GDCLASS(BBFloat64Array, BBParam);
|
GDCLASS(BBFloat64Array, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_FLOAT64_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_FLOAT64_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBInt : public BBParam {
|
||||||
GDCLASS(BBInt, BBParam);
|
GDCLASS(BBInt, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::INT; }
|
virtual Variant::Type get_type() const override { return Variant::INT; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBInt32Array : public BBParam {
|
||||||
GDCLASS(BBInt32Array, BBParam);
|
GDCLASS(BBInt32Array, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_INT32_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_INT32_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBInt64Array : public BBParam {
|
||||||
GDCLASS(BBInt64Array, BBParam);
|
GDCLASS(BBInt64Array, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_INT64_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_INT64_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
#include <godot_cpp/classes/node.hpp>
|
#include <godot_cpp/classes/node.hpp>
|
||||||
#endif // LIMBOAI_GDEXTENSION
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
|
||||||
Variant BBNode::get_value(Object *p_agent, const Ref<Blackboard> &p_blackboard, const Variant &p_default) {
|
Variant BBNode::get_value(Node *p_scene_root, const Ref<Blackboard> &p_blackboard, const Variant &p_default) {
|
||||||
ERR_FAIL_COND_V(p_agent == nullptr, Variant());
|
ERR_FAIL_NULL_V_MSG(p_scene_root, Variant(), "BBNode: get_value() failed - scene_root is null.");
|
||||||
ERR_FAIL_COND_V(!p_blackboard.is_valid(), Variant());
|
ERR_FAIL_NULL_V_MSG(p_blackboard, Variant(), "BBNode: get_value() failed - blackboard is null.");
|
||||||
|
|
||||||
Variant val;
|
Variant val;
|
||||||
if (get_value_source() == SAVED_VALUE) {
|
if (get_value_source() == SAVED_VALUE) {
|
||||||
|
@ -32,9 +32,7 @@ Variant BBNode::get_value(Object *p_agent, const Ref<Blackboard> &p_blackboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val.get_type() == Variant::NODE_PATH) {
|
if (val.get_type() == Variant::NODE_PATH) {
|
||||||
Node *agent = Object::cast_to<Node>(p_agent);
|
return p_scene_root->get_node_or_null(val);
|
||||||
ERR_FAIL_COND_V_MSG(agent == nullptr, Variant(), "BBNode: p_agent must be a Node.");
|
|
||||||
return agent->get_node_or_null(val);
|
|
||||||
} else {
|
} else {
|
||||||
Object *obj = val;
|
Object *obj = val;
|
||||||
if (unlikely(obj == nullptr && val.get_type() != Variant::NIL)) {
|
if (unlikely(obj == nullptr && val.get_type() != Variant::NIL)) {
|
||||||
|
|
|
@ -18,10 +18,11 @@ class BBNode : public BBParam {
|
||||||
GDCLASS(BBNode, BBParam);
|
GDCLASS(BBNode, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Variant::Type get_type() const override { return Variant::NODE_PATH; }
|
static void _bind_methods() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Variant get_value(Object *p_agent, const Ref<Blackboard> &p_blackboard, const Variant &p_default = Variant()) override;
|
virtual Variant::Type get_type() const override { return Variant::NODE_PATH; }
|
||||||
|
virtual Variant get_value(Node *p_scene_root, const Ref<Blackboard> &p_blackboard, const Variant &p_default = Variant()) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BB_NODE_H
|
#endif // BB_NODE_H
|
||||||
|
|
|
@ -75,7 +75,7 @@ String BBParam::_to_string() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant BBParam::get_value(Object *p_agent, const Ref<Blackboard> &p_blackboard, const Variant &p_default) {
|
Variant BBParam::get_value(Node *p_scene_root, const Ref<Blackboard> &p_blackboard, const Variant &p_default) {
|
||||||
ERR_FAIL_COND_V(!p_blackboard.is_valid(), p_default);
|
ERR_FAIL_COND_V(!p_blackboard.is_valid(), p_default);
|
||||||
|
|
||||||
if (value_source == SAVED_VALUE) {
|
if (value_source == SAVED_VALUE) {
|
||||||
|
@ -105,7 +105,7 @@ void BBParam::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_variable", "variable_name"), &BBParam::set_variable);
|
ClassDB::bind_method(D_METHOD("set_variable", "variable_name"), &BBParam::set_variable);
|
||||||
ClassDB::bind_method(D_METHOD("get_variable"), &BBParam::get_variable);
|
ClassDB::bind_method(D_METHOD("get_variable"), &BBParam::get_variable);
|
||||||
ClassDB::bind_method(D_METHOD("get_type"), &BBParam::get_type);
|
ClassDB::bind_method(D_METHOD("get_type"), &BBParam::get_type);
|
||||||
ClassDB::bind_method(D_METHOD("get_value", "agent", "blackboard", "default"), &BBParam::get_value, Variant());
|
ClassDB::bind_method(D_METHOD("get_value", "scene_root", "blackboard", "default"), &BBParam::get_value, Variant());
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "value_source", PROPERTY_HINT_ENUM, "Saved Value,Blackboard Var"), "set_value_source", "get_value_source");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "value_source", PROPERTY_HINT_ENUM, "Saved Value,Blackboard Var"), "set_value_source", "get_value_source");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "variable", PROPERTY_HINT_NONE, "", 0), "set_variable", "get_variable");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "variable", PROPERTY_HINT_NONE, "", 0), "set_variable", "get_variable");
|
||||||
|
|
|
@ -49,8 +49,6 @@ protected:
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Variant::Type get_type() const { return Variant::NIL; }
|
|
||||||
|
|
||||||
void set_value_source(ValueSource p_value);
|
void set_value_source(ValueSource p_value);
|
||||||
ValueSource get_value_source() const { return value_source; }
|
ValueSource get_value_source() const { return value_source; }
|
||||||
|
|
||||||
|
@ -66,7 +64,9 @@ public:
|
||||||
virtual String _to_string();
|
virtual String _to_string();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual Variant get_value(Object *p_agent, const Ref<Blackboard> &p_blackboard, const Variant &p_default = Variant());
|
virtual Variant::Type get_type() const { return Variant::NIL; }
|
||||||
|
virtual Variant::Type get_variable_expected_type() const { return get_type(); }
|
||||||
|
virtual Variant get_value(Node *p_scene_root, const Ref<Blackboard> &p_blackboard, const Variant &p_default = Variant());
|
||||||
|
|
||||||
BBParam();
|
BBParam();
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBPlane : public BBParam {
|
||||||
GDCLASS(BBPlane, BBParam);
|
GDCLASS(BBPlane, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PLANE; }
|
virtual Variant::Type get_type() const override { return Variant::PLANE; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBProjection : public BBParam {
|
||||||
GDCLASS(BBProjection, BBParam);
|
GDCLASS(BBProjection, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PROJECTION; }
|
virtual Variant::Type get_type() const override { return Variant::PROJECTION; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBQuaternion : public BBParam {
|
||||||
GDCLASS(BBQuaternion, BBParam);
|
GDCLASS(BBQuaternion, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::QUATERNION; }
|
virtual Variant::Type get_type() const override { return Variant::QUATERNION; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBRect2 : public BBParam {
|
||||||
GDCLASS(BBRect2, BBParam);
|
GDCLASS(BBRect2, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::RECT2; }
|
virtual Variant::Type get_type() const override { return Variant::RECT2; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBRect2i : public BBParam {
|
||||||
GDCLASS(BBRect2i, BBParam);
|
GDCLASS(BBRect2i, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::RECT2I; }
|
virtual Variant::Type get_type() const override { return Variant::RECT2I; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBString : public BBParam {
|
||||||
GDCLASS(BBString, BBParam);
|
GDCLASS(BBString, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::STRING; }
|
virtual Variant::Type get_type() const override { return Variant::STRING; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBStringArray : public BBParam {
|
||||||
GDCLASS(BBStringArray, BBParam);
|
GDCLASS(BBStringArray, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_STRING_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_STRING_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBStringName : public BBParam {
|
||||||
GDCLASS(BBStringName, BBParam);
|
GDCLASS(BBStringName, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::STRING_NAME; }
|
virtual Variant::Type get_type() const override { return Variant::STRING_NAME; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBTransform2D : public BBParam {
|
||||||
GDCLASS(BBTransform2D, BBParam);
|
GDCLASS(BBTransform2D, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::TRANSFORM2D; }
|
virtual Variant::Type get_type() const override { return Variant::TRANSFORM2D; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBTransform3D : public BBParam {
|
||||||
GDCLASS(BBTransform3D, BBParam);
|
GDCLASS(BBTransform3D, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::TRANSFORM3D; }
|
virtual Variant::Type get_type() const override { return Variant::TRANSFORM3D; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
virtual Variant::Type get_type() const override;
|
virtual Variant::Type get_type() const override;
|
||||||
void set_type(Variant::Type p_type);
|
void set_type(Variant::Type p_type);
|
||||||
|
|
||||||
|
virtual Variant::Type get_variable_expected_type() const override { return Variant::NIL; }
|
||||||
|
|
||||||
BBVariant(const Variant &p_value);
|
BBVariant(const Variant &p_value);
|
||||||
BBVariant();
|
BBVariant();
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector2 : public BBParam {
|
||||||
GDCLASS(BBVector2, BBParam);
|
GDCLASS(BBVector2, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::VECTOR2; }
|
virtual Variant::Type get_type() const override { return Variant::VECTOR2; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector2Array : public BBParam {
|
||||||
GDCLASS(BBVector2Array, BBParam);
|
GDCLASS(BBVector2Array, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_VECTOR2_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_VECTOR2_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector2i : public BBParam {
|
||||||
GDCLASS(BBVector2i, BBParam);
|
GDCLASS(BBVector2i, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::VECTOR2I; }
|
virtual Variant::Type get_type() const override { return Variant::VECTOR2I; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector3 : public BBParam {
|
||||||
GDCLASS(BBVector3, BBParam);
|
GDCLASS(BBVector3, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::VECTOR3; }
|
virtual Variant::Type get_type() const override { return Variant::VECTOR3; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector3Array : public BBParam {
|
||||||
GDCLASS(BBVector3Array, BBParam);
|
GDCLASS(BBVector3Array, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::PACKED_VECTOR3_ARRAY; }
|
virtual Variant::Type get_type() const override { return Variant::PACKED_VECTOR3_ARRAY; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector3i : public BBParam {
|
||||||
GDCLASS(BBVector3i, BBParam);
|
GDCLASS(BBVector3i, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::VECTOR3I; }
|
virtual Variant::Type get_type() const override { return Variant::VECTOR3I; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector4 : public BBParam {
|
||||||
GDCLASS(BBVector4, BBParam);
|
GDCLASS(BBVector4, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::VECTOR4; }
|
virtual Variant::Type get_type() const override { return Variant::VECTOR4; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BBVector4i : public BBParam {
|
||||||
GDCLASS(BBVector4i, BBParam);
|
GDCLASS(BBVector4i, BBParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Variant::Type get_type() const override { return Variant::VECTOR4I; }
|
virtual Variant::Type get_type() const override { return Variant::VECTOR4I; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,36 @@ void Blackboard::erase_var(const StringName &p_name) {
|
||||||
data.erase(p_name);
|
data.erase(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypedArray<StringName> Blackboard::list_vars() const {
|
||||||
|
TypedArray<StringName> var_names;
|
||||||
|
var_names.resize(data.size());
|
||||||
|
int idx = 0;
|
||||||
|
for (const KeyValue<StringName, BBVariable> &kv : data) {
|
||||||
|
var_names[idx] = kv.key;
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
return var_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary Blackboard::get_vars_as_dict() const {
|
||||||
|
Dictionary dict;
|
||||||
|
for (const KeyValue<StringName, BBVariable> &kv : data) {
|
||||||
|
dict[kv.key] = kv.value.get_value();
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blackboard::populate_from_dict(const Dictionary &p_dictionary) {
|
||||||
|
Array keys = p_dictionary.keys();
|
||||||
|
for (int i = 0; i < keys.size(); i++) {
|
||||||
|
if (keys[i].get_type() == Variant::STRING_NAME || keys[i].get_type() == Variant::STRING) {
|
||||||
|
set_var(keys[i], p_dictionary[keys[i]]);
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Blackboard: Invalid key type in dictionary to populate blackboard. Must be StringName or String.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Blackboard::bind_var_to_property(const StringName &p_name, Object *p_object, const StringName &p_property, bool p_create) {
|
void Blackboard::bind_var_to_property(const StringName &p_name, Object *p_object, const StringName &p_property, bool p_create) {
|
||||||
if (!data.has(p_name)) {
|
if (!data.has(p_name)) {
|
||||||
if (p_create) {
|
if (p_create) {
|
||||||
|
@ -76,7 +106,7 @@ void Blackboard::bind_var_to_property(const StringName &p_name, Object *p_object
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blackboard::unbind_var(const StringName &p_name) {
|
void Blackboard::unbind_var(const StringName &p_name) {
|
||||||
ERR_FAIL_COND_MSG(data.has(p_name), "Blackboard: Can't unbind variable that doesn't exist (var: " + p_name + ").");
|
ERR_FAIL_COND_MSG(!data.has(p_name), "Blackboard: Can't unbind variable that doesn't exist (var: " + p_name + ").");
|
||||||
data[p_name].unbind();
|
data[p_name].unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,12 +128,16 @@ void Blackboard::link_var(const StringName &p_name, const Ref<Blackboard> &p_tar
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blackboard::_bind_methods() {
|
void Blackboard::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_var", "var_name", "default", "complain"), &Blackboard::get_var, Variant(), true);
|
ClassDB::bind_method(D_METHOD("get_var", "var_name", "default", "complain"), &Blackboard::get_var, DEFVAL(Variant()), DEFVAL(true));
|
||||||
ClassDB::bind_method(D_METHOD("set_var", "var_name", "value"), &Blackboard::set_var);
|
ClassDB::bind_method(D_METHOD("set_var", "var_name", "value"), &Blackboard::set_var);
|
||||||
ClassDB::bind_method(D_METHOD("has_var", "var_name"), &Blackboard::has_var);
|
ClassDB::bind_method(D_METHOD("has_var", "var_name"), &Blackboard::has_var);
|
||||||
ClassDB::bind_method(D_METHOD("set_parent", "blackboard"), &Blackboard::set_parent);
|
ClassDB::bind_method(D_METHOD("set_parent", "blackboard"), &Blackboard::set_parent);
|
||||||
ClassDB::bind_method(D_METHOD("get_parent"), &Blackboard::get_parent);
|
ClassDB::bind_method(D_METHOD("get_parent"), &Blackboard::get_parent);
|
||||||
ClassDB::bind_method(D_METHOD("erase_var", "var_name"), &Blackboard::erase_var);
|
ClassDB::bind_method(D_METHOD("erase_var", "var_name"), &Blackboard::erase_var);
|
||||||
|
ClassDB::bind_method(D_METHOD("clear"), &Blackboard::clear);
|
||||||
|
ClassDB::bind_method(D_METHOD("list_vars"), &Blackboard::list_vars);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_vars_as_dict"), &Blackboard::get_vars_as_dict);
|
||||||
|
ClassDB::bind_method(D_METHOD("populate_from_dict", "dictionary"), &Blackboard::populate_from_dict);
|
||||||
ClassDB::bind_method(D_METHOD("top"), &Blackboard::top);
|
ClassDB::bind_method(D_METHOD("top"), &Blackboard::top);
|
||||||
ClassDB::bind_method(D_METHOD("bind_var_to_property", "var_name", "object", "property", "create"), &Blackboard::bind_var_to_property, DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("bind_var_to_property", "var_name", "object", "property", "create"), &Blackboard::bind_var_to_property, DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("unbind_var", "var_name"), &Blackboard::unbind_var);
|
ClassDB::bind_method(D_METHOD("unbind_var", "var_name"), &Blackboard::unbind_var);
|
||||||
|
|
|
@ -46,10 +46,15 @@ public:
|
||||||
|
|
||||||
Ref<Blackboard> top() const;
|
Ref<Blackboard> top() const;
|
||||||
|
|
||||||
Variant get_var(const StringName &p_name, const Variant &p_default, bool p_complain = true) const;
|
Variant get_var(const StringName &p_name, const Variant &p_default = Variant(), bool p_complain = true) const;
|
||||||
void set_var(const StringName &p_name, const Variant &p_value);
|
void set_var(const StringName &p_name, const Variant &p_value);
|
||||||
bool has_var(const StringName &p_name) const;
|
bool has_var(const StringName &p_name) const;
|
||||||
void erase_var(const StringName &p_name);
|
void erase_var(const StringName &p_name);
|
||||||
|
void clear() { data.clear(); }
|
||||||
|
TypedArray<StringName> list_vars() const;
|
||||||
|
|
||||||
|
Dictionary get_vars_as_dict() const;
|
||||||
|
void populate_from_dict(const Dictionary &p_dictionary);
|
||||||
|
|
||||||
void bind_var_to_property(const StringName &p_name, Object *p_object, const StringName &p_property, bool p_create = false);
|
void bind_var_to_property(const StringName &p_name, Object *p_object, const StringName &p_property, bool p_create = false);
|
||||||
void unbind_var(const StringName &p_name);
|
void unbind_var(const StringName &p_name);
|
||||||
|
@ -57,8 +62,6 @@ public:
|
||||||
void assign_var(const StringName &p_name, const BBVariable &p_var);
|
void assign_var(const StringName &p_name, const BBVariable &p_var);
|
||||||
|
|
||||||
void link_var(const StringName &p_name, const Ref<Blackboard> &p_target_blackboard, const StringName &p_target_var, bool p_create = false);
|
void link_var(const StringName &p_name, const Ref<Blackboard> &p_target_blackboard, const StringName &p_target_var, bool p_create = false);
|
||||||
|
|
||||||
// TODO: Add serialization API.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BLACKBOARD_H
|
#endif // BLACKBOARD_H
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "blackboard_plan.h"
|
#include "blackboard_plan.h"
|
||||||
|
|
||||||
|
#include "../util/limbo_utility.h"
|
||||||
|
|
||||||
bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
|
bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
String name_str = p_name;
|
String name_str = p_name;
|
||||||
|
|
||||||
|
@ -25,6 +27,28 @@ bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * Mapping
|
||||||
|
if (name_str.begins_with("mapping/")) {
|
||||||
|
StringName mapped_var_name = name_str.get_slicec('/', 1);
|
||||||
|
StringName value = p_value;
|
||||||
|
bool properties_changed = false;
|
||||||
|
if (value == StringName()) {
|
||||||
|
if (parent_scope_mapping.has(mapped_var_name)) {
|
||||||
|
properties_changed = true;
|
||||||
|
parent_scope_mapping.erase(mapped_var_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!parent_scope_mapping.has(mapped_var_name)) {
|
||||||
|
properties_changed = true;
|
||||||
|
}
|
||||||
|
parent_scope_mapping[mapped_var_name] = value;
|
||||||
|
}
|
||||||
|
if (properties_changed) {
|
||||||
|
notify_property_list_changed();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// * Storage
|
// * Storage
|
||||||
if (name_str.begins_with("var/")) {
|
if (name_str.begins_with("var/")) {
|
||||||
StringName var_name = name_str.get_slicec('/', 1);
|
StringName var_name = name_str.get_slicec('/', 1);
|
||||||
|
@ -56,7 +80,23 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
|
|
||||||
// * Editor
|
// * Editor
|
||||||
if (var_map.has(p_name)) {
|
if (var_map.has(p_name)) {
|
||||||
|
if (has_mapping(p_name)) {
|
||||||
|
r_ret = "Mapped to " + LimboUtility::get_singleton()->decorate_var(parent_scope_mapping[p_name]);
|
||||||
|
} else {
|
||||||
r_ret = var_map[p_name].get_value();
|
r_ret = var_map[p_name].get_value();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// * Mapping
|
||||||
|
if (name_str.begins_with("mapping/")) {
|
||||||
|
StringName mapped_var_name = name_str.get_slicec('/', 1);
|
||||||
|
ERR_FAIL_COND_V(mapped_var_name == StringName(), false);
|
||||||
|
if (parent_scope_mapping.has(mapped_var_name)) {
|
||||||
|
r_ret = parent_scope_mapping[mapped_var_name];
|
||||||
|
} else {
|
||||||
|
r_ret = StringName();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +104,6 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
if (!name_str.begins_with("var/")) {
|
if (!name_str.begins_with("var/")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringName var_name = name_str.get_slicec('/', 1);
|
StringName var_name = name_str.get_slicec('/', 1);
|
||||||
String what = name_str.get_slicec('/', 2);
|
String what = name_str.get_slicec('/', 2);
|
||||||
ERR_FAIL_COND_V(!var_map.has(var_name), false);
|
ERR_FAIL_COND_V(!var_map.has(var_name), false);
|
||||||
|
@ -90,29 +129,49 @@ void BlackboardPlan::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
|
|
||||||
// * Editor
|
// * Editor
|
||||||
if (var.get_type() != Variant::NIL && (!is_derived() || !var_name.begins_with("_"))) {
|
if (var.get_type() != Variant::NIL && (!is_derived() || !var_name.begins_with("_"))) {
|
||||||
|
if (has_mapping(var_name)) {
|
||||||
|
p_list->push_back(PropertyInfo(Variant::STRING, var_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY));
|
||||||
|
} else {
|
||||||
p_list->push_back(PropertyInfo(var.get_type(), var_name, var.get_hint(), var.get_hint_string(), PROPERTY_USAGE_EDITOR));
|
p_list->push_back(PropertyInfo(var.get_type(), var_name, var.get_hint(), var.get_hint_string(), PROPERTY_USAGE_EDITOR));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// * Storage
|
||||||
if (is_derived() && (!var.is_value_changed() || var.get_value() == base->var_map[var_name].get_value())) {
|
if (is_derived() && (!var.is_value_changed() || var.get_value() == base->var_map[var_name].get_value())) {
|
||||||
// Don't store variable if it's not modified in a derived plan.
|
// Don't store variable if it's not modified in a derived plan.
|
||||||
// Variable is considered modified when it's marked as changed and its value is different from the base plan.
|
// Variable is considered modified when it's marked as changed and its value is different from the base plan.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// * Storage
|
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, "var/" + var_name + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
p_list->push_back(PropertyInfo(Variant::STRING, "var/" + var_name + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
||||||
p_list->push_back(PropertyInfo(Variant::INT, "var/" + var_name + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
p_list->push_back(PropertyInfo(Variant::INT, "var/" + var_name + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
||||||
p_list->push_back(PropertyInfo(var.get_type(), "var/" + var_name + "/value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
p_list->push_back(PropertyInfo(var.get_type(), "var/" + var_name + "/value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
||||||
p_list->push_back(PropertyInfo(Variant::INT, "var/" + var_name + "/hint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
p_list->push_back(PropertyInfo(Variant::INT, "var/" + var_name + "/hint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, "var/" + var_name + "/hint_string", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
p_list->push_back(PropertyInfo(Variant::STRING, "var/" + var_name + "/hint_string", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * Mapping
|
||||||
|
if (is_mapping_enabled()) {
|
||||||
|
p_list->push_back(PropertyInfo(Variant::NIL, "Mapping", PROPERTY_HINT_NONE, "mapping/", PROPERTY_USAGE_GROUP));
|
||||||
|
for (const Pair<StringName, BBVariable> &p : var_list) {
|
||||||
|
// Serialize only non-empty mappings.
|
||||||
|
PropertyUsageFlags usage = has_mapping(p.first) ? PROPERTY_USAGE_DEFAULT : PROPERTY_USAGE_EDITOR;
|
||||||
|
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "mapping/" + p.first, PROPERTY_HINT_NONE, "", usage));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlackboardPlan::_property_can_revert(const StringName &p_name) const {
|
bool BlackboardPlan::_property_can_revert(const StringName &p_name) const {
|
||||||
|
if (String(p_name).begins_with("mapping/")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return base.is_valid() && base->var_map.has(p_name);
|
return base.is_valid() && base->var_map.has(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_property) const {
|
bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_property) const {
|
||||||
|
if (String(p_name).begins_with("mapping/")) {
|
||||||
|
r_property = StringName();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (base->var_map.has(p_name)) {
|
if (base->var_map.has(p_name)) {
|
||||||
r_property = base->var_map[p_name].get_value();
|
r_property = base->var_map[p_name].get_value();
|
||||||
return true;
|
return true;
|
||||||
|
@ -131,6 +190,15 @@ void BlackboardPlan::set_base_plan(const Ref<BlackboardPlan> &p_base) {
|
||||||
notify_property_list_changed();
|
notify_property_list_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlackboardPlan::set_parent_scope_plan_provider(const Callable &p_parent_scope_plan_provider) {
|
||||||
|
parent_scope_plan_provider = p_parent_scope_plan_provider;
|
||||||
|
notify_property_list_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlackboardPlan::has_mapping(const StringName &p_name) const {
|
||||||
|
return is_mapping_enabled() && parent_scope_mapping.has(p_name) && parent_scope_mapping[p_name] != StringName();
|
||||||
|
}
|
||||||
|
|
||||||
void BlackboardPlan::set_prefetch_nodepath_vars(bool p_enable) {
|
void BlackboardPlan::set_prefetch_nodepath_vars(bool p_enable) {
|
||||||
prefetch_nodepath_vars = p_enable;
|
prefetch_nodepath_vars = p_enable;
|
||||||
emit_changed();
|
emit_changed();
|
||||||
|
@ -169,11 +237,11 @@ BBVariable BlackboardPlan::get_var(const StringName &p_name) {
|
||||||
Pair<StringName, BBVariable> BlackboardPlan::get_var_by_index(int p_index) {
|
Pair<StringName, BBVariable> BlackboardPlan::get_var_by_index(int p_index) {
|
||||||
Pair<StringName, BBVariable> ret;
|
Pair<StringName, BBVariable> ret;
|
||||||
ERR_FAIL_INDEX_V(p_index, (int)var_map.size(), ret);
|
ERR_FAIL_INDEX_V(p_index, (int)var_map.size(), ret);
|
||||||
return var_list[p_index];
|
return var_list.get(p_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackedStringArray BlackboardPlan::list_vars() const {
|
TypedArray<StringName> BlackboardPlan::list_vars() const {
|
||||||
PackedStringArray ret;
|
TypedArray<StringName> ret;
|
||||||
for (const Pair<StringName, BBVariable> &p : var_list) {
|
for (const Pair<StringName, BBVariable> &p : var_list) {
|
||||||
ret.append(p.first);
|
ret.append(p.first);
|
||||||
}
|
}
|
||||||
|
@ -214,6 +282,11 @@ void BlackboardPlan::rename_var(const StringName &p_name, const StringName &p_ne
|
||||||
var_map.erase(p_name);
|
var_map.erase(p_name);
|
||||||
var_map.insert(p_new_name, var);
|
var_map.insert(p_new_name, var);
|
||||||
|
|
||||||
|
if (parent_scope_mapping.has(p_name)) {
|
||||||
|
parent_scope_mapping[p_new_name] = parent_scope_mapping[p_name];
|
||||||
|
parent_scope_mapping.erase(p_name);
|
||||||
|
}
|
||||||
|
|
||||||
notify_property_list_changed();
|
notify_property_list_changed();
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
@ -335,12 +408,11 @@ inline void bb_add_var_dup_with_prefetch(const Ref<Blackboard> &p_blackboard, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Blackboard> BlackboardPlan::create_blackboard(Node *p_node) {
|
Ref<Blackboard> BlackboardPlan::create_blackboard(Node *p_node, const Ref<Blackboard> &p_parent_scope) {
|
||||||
ERR_FAIL_COND_V(p_node == nullptr && prefetch_nodepath_vars, memnew(Blackboard));
|
ERR_FAIL_COND_V(p_node == nullptr && prefetch_nodepath_vars, memnew(Blackboard));
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
for (const Pair<StringName, BBVariable> &p : var_list) {
|
bb->set_parent(p_parent_scope);
|
||||||
bb_add_var_dup_with_prefetch(bb, p.first, p.second, prefetch_nodepath_vars, p_node);
|
populate_blackboard(bb, true, p_node);
|
||||||
}
|
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +423,13 @@ void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bo
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bb_add_var_dup_with_prefetch(p_blackboard, p.first, p.second, prefetch_nodepath_vars, p_node);
|
bb_add_var_dup_with_prefetch(p_blackboard, p.first, p.second, prefetch_nodepath_vars, p_node);
|
||||||
|
if (parent_scope_mapping.has(p.first)) {
|
||||||
|
StringName target_var = parent_scope_mapping[p.first];
|
||||||
|
if (target_var != StringName()) {
|
||||||
|
ERR_CONTINUE_MSG(p_blackboard->get_parent() == nullptr, vformat("BlackboardPlan: Cannot link variable $%s to parent scope because the parent scope is not set.", p.first));
|
||||||
|
p_blackboard->link_var(p.first, p_blackboard->get_parent(), target_var);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +441,9 @@ void BlackboardPlan::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan);
|
ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan);
|
||||||
ClassDB::bind_method(D_METHOD("is_derived"), &BlackboardPlan::is_derived);
|
ClassDB::bind_method(D_METHOD("is_derived"), &BlackboardPlan::is_derived);
|
||||||
ClassDB::bind_method(D_METHOD("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan);
|
ClassDB::bind_method(D_METHOD("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan);
|
||||||
ClassDB::bind_method(D_METHOD("create_blackboard", "node"), &BlackboardPlan::create_blackboard);
|
ClassDB::bind_method(D_METHOD("set_parent_scope_plan_provider", "callable"), &BlackboardPlan::set_parent_scope_plan_provider);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_parent_scope_plan_provider"), &BlackboardPlan::get_parent_scope_plan_provider);
|
||||||
|
ClassDB::bind_method(D_METHOD("create_blackboard", "node", "parent_scope"), &BlackboardPlan::create_blackboard, DEFVAL(Ref<Blackboard>()));
|
||||||
ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite", "node"), &BlackboardPlan::populate_blackboard);
|
ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite", "node"), &BlackboardPlan::populate_blackboard);
|
||||||
|
|
||||||
// To avoid cluttering the member namespace, we do not export unnecessary properties in this class.
|
// To avoid cluttering the member namespace, we do not export unnecessary properties in this class.
|
||||||
|
|
|
@ -36,6 +36,13 @@ private:
|
||||||
// and only the values can be different in those variables.
|
// and only the values can be different in those variables.
|
||||||
Ref<BlackboardPlan> base;
|
Ref<BlackboardPlan> base;
|
||||||
|
|
||||||
|
// Mapping between variables in this plan and their parent scope names.
|
||||||
|
// Used for linking variables to their parent scope counterparts upon Blackboard creation/population.
|
||||||
|
HashMap<StringName, StringName> parent_scope_mapping;
|
||||||
|
// Fetcher function for the parent scope plan. Funtion should return a Ref<BlackboardPlan>.
|
||||||
|
// Used in the inspector. When set, mapping feature becomes available.
|
||||||
|
Callable parent_scope_plan_provider;
|
||||||
|
|
||||||
// If true, NodePath variables will be prefetched, so that the vars will contain node pointers instead (upon BB creation/population).
|
// If true, NodePath variables will be prefetched, so that the vars will contain node pointers instead (upon BB creation/population).
|
||||||
bool prefetch_nodepath_vars = true;
|
bool prefetch_nodepath_vars = true;
|
||||||
|
|
||||||
|
@ -52,6 +59,12 @@ public:
|
||||||
void set_base_plan(const Ref<BlackboardPlan> &p_base);
|
void set_base_plan(const Ref<BlackboardPlan> &p_base);
|
||||||
Ref<BlackboardPlan> get_base_plan() const { return base; }
|
Ref<BlackboardPlan> get_base_plan() const { return base; }
|
||||||
|
|
||||||
|
void set_parent_scope_plan_provider(const Callable &p_parent_scope_plan_provider);
|
||||||
|
Callable get_parent_scope_plan_provider() const { return parent_scope_plan_provider; }
|
||||||
|
|
||||||
|
bool is_mapping_enabled() const { return parent_scope_plan_provider.is_valid() && (parent_scope_plan_provider.call() != Ref<BlackboardPlan>()); }
|
||||||
|
bool has_mapping(const StringName &p_name) const;
|
||||||
|
|
||||||
void set_prefetch_nodepath_vars(bool p_enable);
|
void set_prefetch_nodepath_vars(bool p_enable);
|
||||||
bool is_prefetching_nodepath_vars() const;
|
bool is_prefetching_nodepath_vars() const;
|
||||||
|
|
||||||
|
@ -63,7 +76,7 @@ public:
|
||||||
_FORCE_INLINE_ bool is_empty() const { return var_map.is_empty(); }
|
_FORCE_INLINE_ bool is_empty() const { return var_map.is_empty(); }
|
||||||
int get_var_count() const { return var_map.size(); }
|
int get_var_count() const { return var_map.size(); }
|
||||||
|
|
||||||
PackedStringArray list_vars() const;
|
TypedArray<StringName> list_vars() const;
|
||||||
StringName get_var_name(const BBVariable &p_var) const;
|
StringName get_var_name(const BBVariable &p_var) const;
|
||||||
bool is_valid_var_name(const StringName &p_name) const;
|
bool is_valid_var_name(const StringName &p_name) const;
|
||||||
void rename_var(const StringName &p_name, const StringName &p_new_name);
|
void rename_var(const StringName &p_name, const StringName &p_new_name);
|
||||||
|
@ -72,7 +85,7 @@ public:
|
||||||
void sync_with_base_plan();
|
void sync_with_base_plan();
|
||||||
_FORCE_INLINE_ bool is_derived() const { return base.is_valid(); }
|
_FORCE_INLINE_ bool is_derived() const { return base.is_valid(); }
|
||||||
|
|
||||||
Ref<Blackboard> create_blackboard(Node *p_agent);
|
Ref<Blackboard> create_blackboard(Node *p_agent, const Ref<Blackboard> &p_parent_scope = Ref<Blackboard>());
|
||||||
void populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite, Node *p_node);
|
void populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite, Node *p_node);
|
||||||
|
|
||||||
BlackboardPlan();
|
BlackboardPlan();
|
||||||
|
|
|
@ -52,7 +52,13 @@ void BehaviorTree::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BehaviorTree::set_root_task(const Ref<BTTask> &p_value) {
|
void BehaviorTree::set_root_task(const Ref<BTTask> &p_value) {
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
_unset_editor_behavior_tree_hint();
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
root_task = p_value;
|
root_task = p_value;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
_set_editor_behavior_tree_hint();
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,10 +77,12 @@ void BehaviorTree::copy_other(const Ref<BehaviorTree> &p_other) {
|
||||||
root_task = p_other->get_root_task();
|
root_task = p_other->get_root_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<BTTask> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard) const {
|
Ref<BTTask> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) const {
|
||||||
ERR_FAIL_COND_V_MSG(root_task == nullptr, memnew(BTTask), "Trying to instance a behavior tree with no valid root task.");
|
ERR_FAIL_COND_V_MSG(root_task == nullptr, memnew(BTTask), "Trying to instance a behavior tree with no valid root task.");
|
||||||
|
ERR_FAIL_NULL_V_MSG(p_agent, memnew(BTTask), "Trying to instance a behavior tree with no valid agent.");
|
||||||
|
ERR_FAIL_NULL_V_MSG(p_scene_root, memnew(BTTask), "Trying to instance a behavior tree with no valid scene root.");
|
||||||
Ref<BTTask> inst = root_task->clone();
|
Ref<BTTask> inst = root_task->clone();
|
||||||
inst->initialize(p_agent, p_blackboard);
|
inst->initialize(p_agent, p_blackboard, p_scene_root);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +91,22 @@ void BehaviorTree::_plan_changed() {
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
|
void BehaviorTree::_set_editor_behavior_tree_hint() {
|
||||||
|
if (root_task.is_valid()) {
|
||||||
|
root_task->data.behavior_tree_id = this->get_instance_id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTree::_unset_editor_behavior_tree_hint() {
|
||||||
|
if (root_task.is_valid()) {
|
||||||
|
root_task->data.behavior_tree_id = ObjectID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
void BehaviorTree::_bind_methods() {
|
void BehaviorTree::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_description", "description"), &BehaviorTree::set_description);
|
ClassDB::bind_method(D_METHOD("set_description", "description"), &BehaviorTree::set_description);
|
||||||
ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description);
|
ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description);
|
||||||
|
@ -92,7 +116,7 @@ void BehaviorTree::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_root_task"), &BehaviorTree::get_root_task);
|
ClassDB::bind_method(D_METHOD("get_root_task"), &BehaviorTree::get_root_task);
|
||||||
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
||||||
ClassDB::bind_method(D_METHOD("copy_other", "other"), &BehaviorTree::copy_other);
|
ClassDB::bind_method(D_METHOD("copy_other", "other"), &BehaviorTree::copy_other);
|
||||||
ClassDB::bind_method(D_METHOD("instantiate", "agent", "blackboard"), &BehaviorTree::instantiate);
|
ClassDB::bind_method(D_METHOD("instantiate", "agent", "blackboard", "scene_root"), &BehaviorTree::instantiate);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_blackboard_plan", "get_blackboard_plan");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_blackboard_plan", "get_blackboard_plan");
|
||||||
|
|
|
@ -34,6 +34,11 @@ private:
|
||||||
|
|
||||||
void _plan_changed();
|
void _plan_changed();
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
void _set_editor_behavior_tree_hint();
|
||||||
|
void _unset_editor_behavior_tree_hint();
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
@ -53,7 +58,7 @@ public:
|
||||||
|
|
||||||
Ref<BehaviorTree> clone() const;
|
Ref<BehaviorTree> clone() const;
|
||||||
void copy_other(const Ref<BehaviorTree> &p_other);
|
void copy_other(const Ref<BehaviorTree> &p_other);
|
||||||
Ref<BTTask> instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard) const;
|
Ref<BTTask> instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) const;
|
||||||
|
|
||||||
BehaviorTree();
|
BehaviorTree();
|
||||||
~BehaviorTree();
|
~BehaviorTree();
|
||||||
|
|
|
@ -50,9 +50,13 @@ void BTPlayer::_load_tree() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tree_instance.unref();
|
tree_instance.unref();
|
||||||
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer: Needs a valid behavior tree.");
|
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer: Initialization failed - needs a valid behavior tree.");
|
||||||
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "BTPlayer: Behavior tree has no valid root task.");
|
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "BTPlayer: Initialization failed - behavior tree has no valid root task.");
|
||||||
tree_instance = behavior_tree->instantiate(get_owner(), blackboard);
|
Node *agent = GET_NODE(this, agent_node);
|
||||||
|
ERR_FAIL_NULL_MSG(agent, vformat("BTPlayer: Initialization failed - can't get agent with path '%s'.", agent_node));
|
||||||
|
Node *scene_root = get_owner();
|
||||||
|
ERR_FAIL_NULL_MSG(scene_root, "BTPlayer: Initialization failed - can't get scene root (make sure the BTPlayer's owner property is set).");
|
||||||
|
tree_instance = behavior_tree->instantiate(agent, blackboard, scene_root);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (IS_DEBUGGER_ACTIVE()) {
|
if (IS_DEBUGGER_ACTIVE()) {
|
||||||
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path());
|
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path());
|
||||||
|
@ -89,6 +93,13 @@ void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BTPlayer::set_agent_node(const NodePath &p_agent_node) {
|
||||||
|
agent_node = p_agent_node;
|
||||||
|
if (tree_instance.is_valid()) {
|
||||||
|
ERR_PRINT("BTPlayer: Agent node cannot be set after the behavior tree is instantiated. This change will not affect the behavior tree instance.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BTPlayer::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
|
void BTPlayer::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
|
||||||
blackboard_plan = p_plan;
|
blackboard_plan = p_plan;
|
||||||
_update_blackboard_plan();
|
_update_blackboard_plan();
|
||||||
|
@ -142,21 +153,31 @@ void BTPlayer::restart() {
|
||||||
void BTPlayer::_set_monitor_performance(bool p_monitor_performance) {
|
void BTPlayer::_set_monitor_performance(bool p_monitor_performance) {
|
||||||
monitor_performance = p_monitor_performance;
|
monitor_performance = p_monitor_performance;
|
||||||
|
|
||||||
if (!get_owner()) {
|
if (!get_owner() && monitor_performance) {
|
||||||
|
// Don't add custom monitor if not in scene.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Performance *perf = Performance::get_singleton();
|
|
||||||
if (monitor_performance) {
|
if (monitor_performance) {
|
||||||
|
_add_custom_monitor();
|
||||||
|
} else {
|
||||||
|
_remove_custom_monitor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::_add_custom_monitor() {
|
||||||
if (monitor_id == StringName()) {
|
if (monitor_id == StringName()) {
|
||||||
monitor_id = vformat("limboai/update_ms|%s_%s_%s", get_owner()->get_name(), get_name(),
|
monitor_id = vformat("LimboAI/update_ms|%s_%s_%s", get_owner()->get_name(), get_name(),
|
||||||
String(itos(get_instance_id())).md5_text().substr(0, 4));
|
String(itos(get_instance_id())).md5_text().substr(0, 4));
|
||||||
}
|
}
|
||||||
if (!perf->has_custom_monitor(monitor_id)) {
|
if (!Performance::get_singleton()->has_custom_monitor(monitor_id)) {
|
||||||
PERFORMANCE_ADD_CUSTOM_MONITOR(monitor_id, callable_mp(this, &BTPlayer::_get_mean_update_time_msec));
|
PERFORMANCE_ADD_CUSTOM_MONITOR(monitor_id, callable_mp(this, &BTPlayer::_get_mean_update_time_msec));
|
||||||
}
|
}
|
||||||
} else if (monitor_id != StringName() && perf->has_custom_monitor(monitor_id)) {
|
}
|
||||||
perf->remove_custom_monitor(monitor_id);
|
|
||||||
|
void BTPlayer::_remove_custom_monitor() {
|
||||||
|
if (monitor_id != StringName() && Performance::get_singleton()->has_custom_monitor(monitor_id)) {
|
||||||
|
Performance::get_singleton()->remove_custom_monitor(monitor_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,9 +215,6 @@ void BTPlayer::_notification(int p_notification) {
|
||||||
_load_tree();
|
_load_tree();
|
||||||
}
|
}
|
||||||
set_active(active);
|
set_active(active);
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
_set_monitor_performance(monitor_performance);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
_update_blackboard_plan();
|
_update_blackboard_plan();
|
||||||
}
|
}
|
||||||
|
@ -206,6 +224,9 @@ void BTPlayer::_notification(int p_notification) {
|
||||||
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
||||||
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path());
|
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path());
|
||||||
}
|
}
|
||||||
|
if (monitor_performance) {
|
||||||
|
_add_custom_monitor();
|
||||||
|
}
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_EXIT_TREE: {
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
|
@ -213,6 +234,9 @@ void BTPlayer::_notification(int p_notification) {
|
||||||
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
||||||
LimboDebugger::get_singleton()->unregister_bt_instance(tree_instance, get_path());
|
LimboDebugger::get_singleton()->unregister_bt_instance(tree_instance, get_path());
|
||||||
}
|
}
|
||||||
|
if (monitor_performance) {
|
||||||
|
_remove_custom_monitor();
|
||||||
|
}
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
|
||||||
if (Engine::get_singleton()->is_editor_hint()) {
|
if (Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
@ -220,7 +244,6 @@ void BTPlayer::_notification(int p_notification) {
|
||||||
behavior_tree->disconnect(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
|
behavior_tree->disconnect(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,6 +251,8 @@ void BTPlayer::_notification(int p_notification) {
|
||||||
void BTPlayer::_bind_methods() {
|
void BTPlayer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_behavior_tree", "behavior_tree"), &BTPlayer::set_behavior_tree);
|
ClassDB::bind_method(D_METHOD("set_behavior_tree", "behavior_tree"), &BTPlayer::set_behavior_tree);
|
||||||
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTPlayer::get_behavior_tree);
|
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTPlayer::get_behavior_tree);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_agent_node", "agent_node"), &BTPlayer::set_agent_node);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_agent_node"), &BTPlayer::get_agent_node);
|
||||||
ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &BTPlayer::set_update_mode);
|
ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &BTPlayer::set_update_mode);
|
||||||
ClassDB::bind_method(D_METHOD("get_update_mode"), &BTPlayer::get_update_mode);
|
ClassDB::bind_method(D_METHOD("get_update_mode"), &BTPlayer::get_update_mode);
|
||||||
ClassDB::bind_method(D_METHOD("set_active", "active"), &BTPlayer::set_active);
|
ClassDB::bind_method(D_METHOD("set_active", "active"), &BTPlayer::set_active);
|
||||||
|
@ -245,6 +270,7 @@ void BTPlayer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_tree_instance"), &BTPlayer::get_tree_instance);
|
ClassDB::bind_method(D_METHOD("get_tree_instance"), &BTPlayer::get_tree_instance);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "agent_node"), "set_agent_node", "get_agent_node");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard");
|
||||||
|
@ -266,6 +292,7 @@ void BTPlayer::_bind_methods() {
|
||||||
|
|
||||||
BTPlayer::BTPlayer() {
|
BTPlayer::BTPlayer() {
|
||||||
blackboard = Ref<Blackboard>(memnew(Blackboard));
|
blackboard = Ref<Blackboard>(memnew(Blackboard));
|
||||||
|
agent_node = LW_NAME(node_pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
BTPlayer::~BTPlayer() {
|
BTPlayer::~BTPlayer() {
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<BehaviorTree> behavior_tree;
|
Ref<BehaviorTree> behavior_tree;
|
||||||
|
NodePath agent_node;
|
||||||
Ref<BlackboardPlan> blackboard_plan;
|
Ref<BlackboardPlan> blackboard_plan;
|
||||||
UpdateMode update_mode = UpdateMode::PHYSICS;
|
UpdateMode update_mode = UpdateMode::PHYSICS;
|
||||||
bool active = true;
|
bool active = true;
|
||||||
|
@ -57,6 +58,9 @@ public:
|
||||||
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
||||||
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
||||||
|
|
||||||
|
void set_agent_node(const NodePath &p_agent_node);
|
||||||
|
NodePath get_agent_node() const { return agent_node; }
|
||||||
|
|
||||||
void set_blackboard_plan(const Ref<BlackboardPlan> &p_plan);
|
void set_blackboard_plan(const Ref<BlackboardPlan> &p_plan);
|
||||||
Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
|
Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
|
||||||
|
|
||||||
|
@ -88,6 +92,10 @@ private:
|
||||||
|
|
||||||
void _set_monitor_performance(bool p_monitor_performance);
|
void _set_monitor_performance(bool p_monitor_performance);
|
||||||
bool _get_monitor_performance() const { return monitor_performance; }
|
bool _get_monitor_performance() const { return monitor_performance; }
|
||||||
|
|
||||||
|
void _add_custom_monitor();
|
||||||
|
void _remove_custom_monitor();
|
||||||
|
|
||||||
double _get_mean_update_time_msec();
|
double _get_mean_update_time_msec();
|
||||||
|
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
|
|
@ -32,10 +32,10 @@ void BTState::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
||||||
p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan));
|
p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan));
|
||||||
}
|
}
|
||||||
behavior_tree = p_tree;
|
behavior_tree = p_tree;
|
||||||
_update_blackboard_plan();
|
|
||||||
} else {
|
} else {
|
||||||
behavior_tree = p_tree;
|
behavior_tree = p_tree;
|
||||||
}
|
}
|
||||||
|
_update_blackboard_plan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTState::_update_blackboard_plan() {
|
void BTState::_update_blackboard_plan() {
|
||||||
|
@ -52,8 +52,9 @@ void BTState::_update_blackboard_plan() {
|
||||||
void BTState::_setup() {
|
void BTState::_setup() {
|
||||||
LimboState::_setup();
|
LimboState::_setup();
|
||||||
ERR_FAIL_COND_MSG(behavior_tree.is_null(), "BTState: BehaviorTree is not assigned.");
|
ERR_FAIL_COND_MSG(behavior_tree.is_null(), "BTState: BehaviorTree is not assigned.");
|
||||||
// TODO: BBNode relies on agent to be scene owner, so if the user provides anything else, the behavior tree can break.
|
Node *scene_root = get_owner();
|
||||||
tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard());
|
ERR_FAIL_NULL_MSG(scene_root, "BTState: Initialization failed - can't get scene root (make sure the BTState's owner property is set).");
|
||||||
|
tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard(), scene_root);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
||||||
|
@ -73,7 +74,7 @@ void BTState::_exit() {
|
||||||
|
|
||||||
void BTState::_update(double p_delta) {
|
void BTState::_update(double p_delta) {
|
||||||
VCALL_ARGS(_update, p_delta);
|
VCALL_ARGS(_update, p_delta);
|
||||||
if (!active) {
|
if (!is_active()) {
|
||||||
// Bail out if a transition happened in the meantime.
|
// Bail out if a transition happened in the meantime.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ BT::Status BTCheckVar::_tick(double p_delta) {
|
||||||
ERR_FAIL_COND_V_MSG(!get_blackboard()->has_var(variable), FAILURE, vformat("BTCheckVar: Blackboard variable doesn't exist: \"%s\". Returning FAILURE.", variable));
|
ERR_FAIL_COND_V_MSG(!get_blackboard()->has_var(variable), FAILURE, vformat("BTCheckVar: Blackboard variable doesn't exist: \"%s\". Returning FAILURE.", variable));
|
||||||
|
|
||||||
Variant left_value = get_blackboard()->get_var(variable, Variant());
|
Variant left_value = get_blackboard()->get_var(variable, Variant());
|
||||||
Variant right_value = value->get_value(get_agent(), get_blackboard());
|
Variant right_value = value->get_value(get_scene_root(), get_blackboard());
|
||||||
|
|
||||||
return LimboUtility::get_singleton()->perform_check(check_type, left_value, right_value) ? SUCCESS : FAILURE;
|
return LimboUtility::get_singleton()->perform_check(check_type, left_value, right_value) ? SUCCESS : FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ BT::Status BTSetVar::_tick(double p_delta) {
|
||||||
ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTSetVar: `value` is not set.");
|
ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTSetVar: `value` is not set.");
|
||||||
Variant result;
|
Variant result;
|
||||||
Variant error_result = LW_NAME(error_value);
|
Variant error_result = LW_NAME(error_value);
|
||||||
Variant right_value = value->get_value(get_agent(), get_blackboard(), error_result);
|
Variant right_value = value->get_value(get_scene_root(), get_blackboard(), error_result);
|
||||||
ERR_FAIL_COND_V_MSG(right_value == error_result, FAILURE, "BTSetVar: Failed to get parameter value. Returning FAILURE.");
|
ERR_FAIL_COND_V_MSG(right_value == error_result, FAILURE, "BTSetVar: Failed to get parameter value. Returning FAILURE.");
|
||||||
if (operation == LimboUtility::OPERATION_NONE) {
|
if (operation == LimboUtility::OPERATION_NONE) {
|
||||||
result = right_value;
|
result = right_value;
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
class BTAction : public BTTask {
|
class BTAction : public BTTask {
|
||||||
GDCLASS(BTAction, BTTask);
|
GDCLASS(BTAction, BTTask);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual PackedStringArray get_configuration_warnings() override;
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,9 @@ class BTComment : public BTTask {
|
||||||
GDCLASS(BTComment, BTTask);
|
GDCLASS(BTComment, BTTask);
|
||||||
TASK_CATEGORY(Utility);
|
TASK_CATEGORY(Utility);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<BTTask> clone() const override;
|
virtual Ref<BTTask> clone() const override;
|
||||||
virtual PackedStringArray get_configuration_warnings() override;
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
class BTComposite : public BTTask {
|
class BTComposite : public BTTask {
|
||||||
GDCLASS(BTComposite, BTTask);
|
GDCLASS(BTComposite, BTTask);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual PackedStringArray get_configuration_warnings() override;
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
class BTCondition : public BTTask {
|
class BTCondition : public BTTask {
|
||||||
GDCLASS(BTCondition, BTTask);
|
GDCLASS(BTCondition, BTTask);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual PackedStringArray get_configuration_warnings() override;
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@ class BTDecorator : public BTTask {
|
||||||
GDCLASS(BTDecorator, BTTask)
|
GDCLASS(BTDecorator, BTTask)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../../blackboard/blackboard.h"
|
#include "../../blackboard/blackboard.h"
|
||||||
#include "../../util/limbo_string_names.h"
|
#include "../../util/limbo_string_names.h"
|
||||||
#include "../../util/limbo_utility.h"
|
#include "../../util/limbo_utility.h"
|
||||||
|
#include "../behavior_tree.h"
|
||||||
#include "bt_comment.h"
|
#include "bt_comment.h"
|
||||||
|
|
||||||
#ifdef LIMBOAI_MODULE
|
#ifdef LIMBOAI_MODULE
|
||||||
|
@ -117,33 +118,33 @@ bool BTTask::is_displayed_collapsed() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
String BTTask::get_task_name() {
|
String BTTask::get_task_name() {
|
||||||
if (data.custom_name.is_empty()) {
|
if (!data.custom_name.is_empty()) {
|
||||||
#ifdef LIMBOAI_MODULE
|
|
||||||
if (get_script_instance() && get_script_instance()->has_method(LW_NAME(_generate_name))) {
|
|
||||||
if (unlikely(!get_script_instance()->get_script()->is_tool())) {
|
|
||||||
ERR_PRINT(vformat("BTTask: Task script should be a \"tool\" script!"));
|
|
||||||
} else {
|
|
||||||
return get_script_instance()->call(LimboStringNames::get_singleton()->_generate_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _generate_name();
|
|
||||||
#elif LIMBOAI_GDEXTENSION
|
|
||||||
Ref<Script> task_script = get_script();
|
|
||||||
if (task_script.is_valid() && task_script->is_tool()) {
|
|
||||||
Variant call_result;
|
|
||||||
VCALL_OR_NATIVE_V(_generate_name, Variant, call_result);
|
|
||||||
ERR_FAIL_COND_V(call_result.get_type() == Variant::NIL, _generate_name());
|
|
||||||
String task_name = call_result;
|
|
||||||
ERR_FAIL_COND_V(task_name.is_empty(), _generate_name());
|
|
||||||
return task_name;
|
|
||||||
} else {
|
|
||||||
return _generate_name();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return data.custom_name;
|
return data.custom_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<Script> task_script = get_script();
|
||||||
|
|
||||||
|
if (task_script.is_valid()) {
|
||||||
|
bool has_generate_method = has_method(LW_NAME(_generate_name));
|
||||||
|
ERR_FAIL_COND_V_MSG(has_generate_method && !task_script->is_tool(), _generate_name(), vformat("BTTask: @tool annotation is required if _generate_name is defined: %s", task_script->get_path()));
|
||||||
|
if (task_script->is_tool() && has_generate_method) {
|
||||||
|
String call_result;
|
||||||
|
VCALL_V(_generate_name, call_result);
|
||||||
|
if (call_result.is_empty() || call_result == "<null>") {
|
||||||
|
// Force reset script instance.
|
||||||
|
set_script(Variant());
|
||||||
|
set_script(task_script);
|
||||||
|
// Retry.
|
||||||
|
VCALL_V(_generate_name, call_result);
|
||||||
|
}
|
||||||
|
ERR_FAIL_COND_V_MSG(call_result.is_empty() || call_result == "<null>", _generate_name(), vformat("BTTask: _generate_name() failed to return a proper name string (%s)", task_script->get_path()));
|
||||||
|
return call_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _generate_name();
|
||||||
|
}
|
||||||
|
|
||||||
Ref<BTTask> BTTask::get_root() const {
|
Ref<BTTask> BTTask::get_root() const {
|
||||||
const BTTask *task = this;
|
const BTTask *task = this;
|
||||||
while (!task->is_root()) {
|
while (!task->is_root()) {
|
||||||
|
@ -159,13 +160,15 @@ void BTTask::set_custom_name(const String &p_name) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void BTTask::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
|
void BTTask::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
||||||
ERR_FAIL_COND(p_agent == nullptr);
|
ERR_FAIL_NULL(p_agent);
|
||||||
ERR_FAIL_COND(p_blackboard == nullptr);
|
ERR_FAIL_NULL(p_blackboard);
|
||||||
|
ERR_FAIL_NULL(p_scene_root);
|
||||||
data.agent = p_agent;
|
data.agent = p_agent;
|
||||||
data.blackboard = p_blackboard;
|
data.blackboard = p_blackboard;
|
||||||
|
data.scene_root = p_scene_root;
|
||||||
for (int i = 0; i < data.children.size(); i++) {
|
for (int i = 0; i < data.children.size(); i++) {
|
||||||
get_child(i)->initialize(p_agent, p_blackboard);
|
get_child(i)->initialize(p_agent, p_blackboard, p_scene_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
VCALL_OR_NATIVE(_setup);
|
VCALL_OR_NATIVE(_setup);
|
||||||
|
@ -374,11 +377,27 @@ void BTTask::print_tree(int p_initial_tabs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
|
Ref<BehaviorTree> BTTask::editor_get_behavior_tree() {
|
||||||
|
BTTask *task = this;
|
||||||
|
while (task->data.behavior_tree_id.is_null() && task->get_parent().is_valid()) {
|
||||||
|
task = task->data.parent;
|
||||||
|
}
|
||||||
|
return Object::cast_to<BehaviorTree>(ObjectDB::get_instance(task->data.behavior_tree_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTTask::editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt) {
|
||||||
|
data.behavior_tree_id = p_bt->get_instance_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
void BTTask::_bind_methods() {
|
void BTTask::_bind_methods() {
|
||||||
// Public Methods.
|
// Public Methods.
|
||||||
ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root);
|
ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root);
|
||||||
ClassDB::bind_method(D_METHOD("get_root"), &BTTask::get_root);
|
ClassDB::bind_method(D_METHOD("get_root"), &BTTask::get_root);
|
||||||
ClassDB::bind_method(D_METHOD("initialize", "agent", "blackboard"), &BTTask::initialize);
|
ClassDB::bind_method(D_METHOD("initialize", "agent", "blackboard", "scene_root"), &BTTask::initialize);
|
||||||
ClassDB::bind_method(D_METHOD("clone"), &BTTask::clone);
|
ClassDB::bind_method(D_METHOD("clone"), &BTTask::clone);
|
||||||
ClassDB::bind_method(D_METHOD("execute", "delta"), &BTTask::execute);
|
ClassDB::bind_method(D_METHOD("execute", "delta"), &BTTask::execute);
|
||||||
ClassDB::bind_method(D_METHOD("get_child", "idx"), &BTTask::get_child);
|
ClassDB::bind_method(D_METHOD("get_child", "idx"), &BTTask::get_child);
|
||||||
|
@ -395,10 +414,14 @@ void BTTask::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("print_tree", "initial_tabs"), &BTTask::print_tree, Variant(0));
|
ClassDB::bind_method(D_METHOD("print_tree", "initial_tabs"), &BTTask::print_tree, Variant(0));
|
||||||
ClassDB::bind_method(D_METHOD("get_task_name"), &BTTask::get_task_name);
|
ClassDB::bind_method(D_METHOD("get_task_name"), &BTTask::get_task_name);
|
||||||
ClassDB::bind_method(D_METHOD("abort"), &BTTask::abort);
|
ClassDB::bind_method(D_METHOD("abort"), &BTTask::abort);
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
ClassDB::bind_method(D_METHOD("editor_get_behavior_tree"), &BTTask::editor_get_behavior_tree);
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
// Properties, setters and getters.
|
// Properties, setters and getters.
|
||||||
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
||||||
ClassDB::bind_method(D_METHOD("set_agent", "agent"), &BTTask::set_agent);
|
ClassDB::bind_method(D_METHOD("set_agent", "agent"), &BTTask::set_agent);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_scene_root"), &BTTask::get_scene_root);
|
||||||
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
||||||
ClassDB::bind_method(D_METHOD("_set_children", "children"), &BTTask::_set_children);
|
ClassDB::bind_method(D_METHOD("_set_children", "children"), &BTTask::_set_children);
|
||||||
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
||||||
|
@ -410,6 +433,7 @@ void BTTask::_bind_methods() {
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_agent", "get_agent");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_agent", "get_agent");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "scene_root", PROPERTY_HINT_NODE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_scene_root");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", PROPERTY_USAGE_NONE), "", "get_blackboard");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", PROPERTY_USAGE_NONE), "", "get_blackboard");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_status");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_status");
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
#endif // LIMBOAI_GDEXTENSION
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
|
||||||
|
class BehaviorTree;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for BTTask.
|
* Base class for BTTask.
|
||||||
* Note: In order to properly return Status in the _tick virtual method (GDVIRTUAL1R...)
|
* Note: In order to properly return Status in the _tick virtual method (GDVIRTUAL1R...)
|
||||||
|
@ -75,12 +77,16 @@ private:
|
||||||
int index = -1;
|
int index = -1;
|
||||||
String custom_name;
|
String custom_name;
|
||||||
Node *agent = nullptr;
|
Node *agent = nullptr;
|
||||||
|
Node *scene_root = nullptr;
|
||||||
Ref<Blackboard> blackboard;
|
Ref<Blackboard> blackboard;
|
||||||
BTTask *parent = nullptr;
|
BTTask *parent = nullptr;
|
||||||
Vector<Ref<BTTask>> children;
|
Vector<Ref<BTTask>> children;
|
||||||
Status status = FRESH;
|
Status status = FRESH;
|
||||||
double elapsed = 0.0;
|
double elapsed = 0.0;
|
||||||
bool display_collapsed = false;
|
bool display_collapsed = false;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
ObjectID behavior_tree_id;
|
||||||
|
#endif
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
Array _get_children() const;
|
Array _get_children() const;
|
||||||
|
@ -116,6 +122,8 @@ public:
|
||||||
_FORCE_INLINE_ Node *get_agent() const { return data.agent; }
|
_FORCE_INLINE_ Node *get_agent() const { return data.agent; }
|
||||||
void set_agent(Node *p_agent) { data.agent = p_agent; }
|
void set_agent(Node *p_agent) { data.agent = p_agent; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Node *get_scene_root() const { return data.scene_root; }
|
||||||
|
|
||||||
void set_display_collapsed(bool p_display_collapsed);
|
void set_display_collapsed(bool p_display_collapsed);
|
||||||
bool is_displayed_collapsed() const;
|
bool is_displayed_collapsed() const;
|
||||||
|
|
||||||
|
@ -126,7 +134,7 @@ public:
|
||||||
Ref<BTTask> get_root() const;
|
Ref<BTTask> get_root() const;
|
||||||
|
|
||||||
virtual Ref<BTTask> clone() const;
|
virtual Ref<BTTask> clone() const;
|
||||||
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard);
|
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root);
|
||||||
virtual PackedStringArray get_configuration_warnings(); // ! Native version.
|
virtual PackedStringArray get_configuration_warnings(); // ! Native version.
|
||||||
|
|
||||||
Status execute(double p_delta);
|
Status execute(double p_delta);
|
||||||
|
@ -159,6 +167,11 @@ public:
|
||||||
|
|
||||||
void print_tree(int p_initial_tabs = 0);
|
void print_tree(int p_initial_tabs = 0);
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Ref<BehaviorTree> editor_get_behavior_tree();
|
||||||
|
void editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt);
|
||||||
|
#endif
|
||||||
|
|
||||||
BTTask();
|
BTTask();
|
||||||
~BTTask();
|
~BTTask();
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ private:
|
||||||
int last_running_idx = 0;
|
int last_running_idx = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual void _enter() override;
|
virtual void _enter() override;
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ private:
|
||||||
int last_running_idx = 0;
|
int last_running_idx = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual void _enter() override;
|
virtual void _enter() override;
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,8 @@ private:
|
||||||
Array indicies;
|
Array indicies;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual void _enter() override;
|
virtual void _enter() override;
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,8 @@ private:
|
||||||
Array indicies;
|
Array indicies;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual void _enter() override;
|
virtual void _enter() override;
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ private:
|
||||||
int last_running_idx = 0;
|
int last_running_idx = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual void _enter() override;
|
virtual void _enter() override;
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,8 @@ private:
|
||||||
int last_running_idx = 0;
|
int last_running_idx = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual void _enter() override;
|
virtual void _enter() override;
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@ class BTAlwaysFail : public BTDecorator {
|
||||||
TASK_CATEGORY(Decorators);
|
TASK_CATEGORY(Decorators);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ class BTAlwaysSucceed : public BTDecorator {
|
||||||
TASK_CATEGORY(Decorators);
|
TASK_CATEGORY(Decorators);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ String BTCooldown::_generate_name() {
|
||||||
|
|
||||||
void BTCooldown::_setup() {
|
void BTCooldown::_setup() {
|
||||||
if (cooldown_state_var == StringName()) {
|
if (cooldown_state_var == StringName()) {
|
||||||
cooldown_state_var = vformat("cooldown_%d", rand());
|
cooldown_state_var = vformat("cooldown_%d", get_instance_id());
|
||||||
}
|
}
|
||||||
get_blackboard()->set_var(cooldown_state_var, false);
|
get_blackboard()->set_var(cooldown_state_var, false);
|
||||||
if (start_cooled) {
|
if (start_cooled) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ class BTInvert : public BTDecorator {
|
||||||
TASK_CATEGORY(Decorators);
|
TASK_CATEGORY(Decorators);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,29 +11,46 @@
|
||||||
|
|
||||||
#include "bt_new_scope.h"
|
#include "bt_new_scope.h"
|
||||||
|
|
||||||
|
#include "../../behavior_tree.h"
|
||||||
|
|
||||||
void BTNewScope::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
|
void BTNewScope::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
|
||||||
blackboard_plan = p_plan;
|
blackboard_plan = p_plan;
|
||||||
if (blackboard_plan.is_null()) {
|
if (blackboard_plan.is_null()) {
|
||||||
blackboard_plan.instantiate();
|
blackboard_plan.instantiate();
|
||||||
}
|
}
|
||||||
|
|
||||||
_update_blackboard_plan();
|
_update_blackboard_plan();
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
if (Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
callable_mp(this, &BTNewScope::_set_parent_scope_plan_from_bt).call_deferred();
|
||||||
|
}
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
|
#ifdef TOOLS_ENABLED
|
||||||
|
void BTNewScope::_set_parent_scope_plan_from_bt() {
|
||||||
|
ERR_FAIL_NULL(get_blackboard_plan());
|
||||||
|
Ref<BehaviorTree> bt = get_root()->editor_get_behavior_tree();
|
||||||
|
ERR_FAIL_NULL(bt);
|
||||||
|
get_blackboard_plan()->set_parent_scope_plan_provider(callable_mp(bt.ptr(), &BehaviorTree::get_blackboard_plan));
|
||||||
|
}
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
|
void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
||||||
ERR_FAIL_COND(p_agent == nullptr);
|
ERR_FAIL_COND(p_agent == nullptr);
|
||||||
ERR_FAIL_COND(p_blackboard == nullptr);
|
ERR_FAIL_COND(p_blackboard == nullptr);
|
||||||
|
|
||||||
Ref<Blackboard> bb;
|
Ref<Blackboard> bb;
|
||||||
if (blackboard_plan.is_valid()) {
|
if (blackboard_plan.is_valid()) {
|
||||||
bb = blackboard_plan->create_blackboard(p_agent);
|
bb = blackboard_plan->create_blackboard(p_agent, p_blackboard);
|
||||||
} else {
|
} else {
|
||||||
bb = Ref<Blackboard>(memnew(Blackboard));
|
bb = Ref<Blackboard>(memnew(Blackboard));
|
||||||
}
|
|
||||||
|
|
||||||
bb->set_parent(p_blackboard);
|
bb->set_parent(p_blackboard);
|
||||||
|
}
|
||||||
BTDecorator::initialize(p_agent, bb);
|
BTDecorator::initialize(p_agent, bb, p_scene_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
BT::Status BTNewScope::_tick(double p_delta) {
|
BT::Status BTNewScope::_tick(double p_delta) {
|
||||||
|
|
|
@ -23,6 +23,10 @@ class BTNewScope : public BTDecorator {
|
||||||
private:
|
private:
|
||||||
Ref<BlackboardPlan> blackboard_plan;
|
Ref<BlackboardPlan> blackboard_plan;
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
void _set_parent_scope_plan_from_bt();
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
@ -34,7 +38,7 @@ protected:
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override;
|
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BT_NEW_SCOPE_H
|
#endif // BT_NEW_SCOPE_H
|
||||||
|
|
|
@ -19,6 +19,8 @@ class BTRepeatUntilFailure : public BTDecorator {
|
||||||
TASK_CATEGORY(Decorators);
|
TASK_CATEGORY(Decorators);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ class BTRepeatUntilSuccess : public BTDecorator {
|
||||||
TASK_CATEGORY(Decorators);
|
TASK_CATEGORY(Decorators);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,14 +44,14 @@ String BTSubtree::_generate_name() {
|
||||||
return vformat("Subtree %s", s);
|
return vformat("Subtree %s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTSubtree::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
|
void BTSubtree::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
||||||
ERR_FAIL_COND_MSG(!subtree.is_valid(), "Subtree is not assigned.");
|
ERR_FAIL_COND_MSG(!subtree.is_valid(), "Subtree is not assigned.");
|
||||||
ERR_FAIL_COND_MSG(!subtree->get_root_task().is_valid(), "Subtree root task is not valid.");
|
ERR_FAIL_COND_MSG(!subtree->get_root_task().is_valid(), "Subtree root task is not valid.");
|
||||||
ERR_FAIL_COND_MSG(get_child_count() != 0, "Subtree task shouldn't have children during initialization.");
|
ERR_FAIL_COND_MSG(get_child_count() != 0, "Subtree task shouldn't have children during initialization.");
|
||||||
|
|
||||||
add_child(subtree->get_root_task()->clone());
|
add_child(subtree->get_root_task()->clone());
|
||||||
|
|
||||||
BTNewScope::initialize(p_agent, p_blackboard);
|
BTNewScope::initialize(p_agent, p_blackboard, p_scene_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
BT::Status BTSubtree::_tick(double p_delta) {
|
BT::Status BTSubtree::_tick(double p_delta) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
void set_subtree(const Ref<BehaviorTree> &p_value);
|
void set_subtree(const Ref<BehaviorTree> &p_value);
|
||||||
Ref<BehaviorTree> get_subtree() const { return subtree; }
|
Ref<BehaviorTree> get_subtree() const { return subtree; }
|
||||||
|
|
||||||
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override;
|
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) override;
|
||||||
virtual PackedStringArray get_configuration_warnings() override;
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
|
|
||||||
BTSubtree() = default;
|
BTSubtree() = default;
|
||||||
|
|
|
@ -62,7 +62,7 @@ String BTAwaitAnimation::_generate_name() {
|
||||||
void BTAwaitAnimation::_setup() {
|
void BTAwaitAnimation::_setup() {
|
||||||
setup_failed = true;
|
setup_failed = true;
|
||||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTAwaitAnimation: AnimationPlayer parameter is not set.");
|
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTAwaitAnimation: AnimationPlayer parameter is not set.");
|
||||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_scene_root(), get_blackboard()));
|
||||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTAwaitAnimation: Failed to get AnimationPlayer.");
|
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTAwaitAnimation: Failed to get AnimationPlayer.");
|
||||||
ERR_FAIL_COND_MSG(animation_name == StringName(), "BTAwaitAnimation: Animation Name is not set.");
|
ERR_FAIL_COND_MSG(animation_name == StringName(), "BTAwaitAnimation: Animation Name is not set.");
|
||||||
ERR_FAIL_COND_MSG(!animation_player->has_animation(animation_name), vformat("BTAwaitAnimation: Animation not found: %s", animation_name));
|
ERR_FAIL_COND_MSG(!animation_player->has_animation(animation_name), vformat("BTAwaitAnimation: Animation not found: %s", animation_name));
|
||||||
|
|
|
@ -62,7 +62,7 @@ BT::Status BTCheckAgentProperty::_tick(double p_delta) {
|
||||||
Variant left_value = get_agent()->get(property);
|
Variant left_value = get_agent()->get(property);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Variant right_value = value->get_value(get_agent(), get_blackboard());
|
Variant right_value = value->get_value(get_scene_root(), get_blackboard());
|
||||||
|
|
||||||
return LimboUtility::get_singleton()->perform_check(check_type, left_value, right_value) ? SUCCESS : FAILURE;
|
return LimboUtility::get_singleton()->perform_check(check_type, left_value, right_value) ? SUCCESS : FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ String BTPauseAnimation::_generate_name() {
|
||||||
void BTPauseAnimation::_setup() {
|
void BTPauseAnimation::_setup() {
|
||||||
setup_failed = true;
|
setup_failed = true;
|
||||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTPauseAnimation: AnimationPlayer parameter is not set.");
|
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTPauseAnimation: AnimationPlayer parameter is not set.");
|
||||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_scene_root(), get_blackboard()));
|
||||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTPauseAnimation: Failed to get AnimationPlayer.");
|
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTPauseAnimation: Failed to get AnimationPlayer.");
|
||||||
setup_failed = false;
|
setup_failed = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ String BTPlayAnimation::_generate_name() {
|
||||||
void BTPlayAnimation::_setup() {
|
void BTPlayAnimation::_setup() {
|
||||||
setup_failed = true;
|
setup_failed = true;
|
||||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTPlayAnimation: AnimationPlayer parameter is not set.");
|
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTPlayAnimation: AnimationPlayer parameter is not set.");
|
||||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_scene_root(), get_blackboard()));
|
||||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTPlayAnimation: Failed to get AnimationPlayer.");
|
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTPlayAnimation: Failed to get AnimationPlayer.");
|
||||||
ERR_FAIL_COND_MSG(animation_name != StringName() && !animation_player->has_animation(animation_name), vformat("BTPlayAnimation: Animation not found: %s", animation_name));
|
ERR_FAIL_COND_MSG(animation_name != StringName() && !animation_player->has_animation(animation_name), vformat("BTPlayAnimation: Animation not found: %s", animation_name));
|
||||||
if (animation_name == StringName() && await_completion > 0.0) {
|
if (animation_name == StringName() && await_completion > 0.0) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ BT::Status BTSetAgentProperty::_tick(double p_delta) {
|
||||||
|
|
||||||
Variant result;
|
Variant result;
|
||||||
StringName error_value = LW_NAME(error_value);
|
StringName error_value = LW_NAME(error_value);
|
||||||
Variant right_value = value->get_value(get_agent(), get_blackboard(), error_value);
|
Variant right_value = value->get_value(get_scene_root(), get_blackboard(), error_value);
|
||||||
ERR_FAIL_COND_V_MSG(right_value == Variant(error_value), FAILURE, "BTSetAgentProperty: Couldn't get value of value-parameter.");
|
ERR_FAIL_COND_V_MSG(right_value == Variant(error_value), FAILURE, "BTSetAgentProperty: Couldn't get value of value-parameter.");
|
||||||
bool r_valid;
|
bool r_valid;
|
||||||
if (operation == LimboUtility::OPERATION_NONE) {
|
if (operation == LimboUtility::OPERATION_NONE) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ String BTStopAnimation::_generate_name() {
|
||||||
void BTStopAnimation::_setup() {
|
void BTStopAnimation::_setup() {
|
||||||
setup_failed = true;
|
setup_failed = true;
|
||||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTStopAnimation: AnimationPlayer parameter is not set.");
|
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTStopAnimation: AnimationPlayer parameter is not set.");
|
||||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_scene_root(), get_blackboard()));
|
||||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTStopAnimation: Failed to get AnimationPlayer.");
|
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTStopAnimation: Failed to get AnimationPlayer.");
|
||||||
if (animation_name != StringName()) {
|
if (animation_name != StringName()) {
|
||||||
ERR_FAIL_COND_MSG(!animation_player->has_animation(animation_name), vformat("BTStopAnimation: Animation not found: %s", animation_name));
|
ERR_FAIL_COND_MSG(!animation_player->has_animation(animation_name), vformat("BTStopAnimation: Animation not found: %s", animation_name));
|
||||||
|
|
|
@ -83,7 +83,7 @@ String BTCallMethod::_generate_name() {
|
||||||
BT::Status BTCallMethod::_tick(double p_delta) {
|
BT::Status BTCallMethod::_tick(double p_delta) {
|
||||||
ERR_FAIL_COND_V_MSG(method == StringName(), FAILURE, "BTCallMethod: Method Name is not set.");
|
ERR_FAIL_COND_V_MSG(method == StringName(), FAILURE, "BTCallMethod: Method Name is not set.");
|
||||||
ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTCallMethod: Node parameter is not set.");
|
ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTCallMethod: Node parameter is not set.");
|
||||||
Object *obj = node_param->get_value(get_agent(), get_blackboard());
|
Object *obj = node_param->get_value(get_scene_root(), get_blackboard());
|
||||||
ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTCallMethod: Failed to get object: " + node_param->to_string());
|
ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTCallMethod: Failed to get object: " + node_param->to_string());
|
||||||
|
|
||||||
Variant result;
|
Variant result;
|
||||||
|
@ -101,7 +101,7 @@ BT::Status BTCallMethod::_tick(double p_delta) {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < args.size(); i++) {
|
for (int i = 0; i < args.size(); i++) {
|
||||||
Ref<BBVariant> param = args[i];
|
Ref<BBVariant> param = args[i];
|
||||||
call_args.push_back(param->get_value(get_agent(), get_blackboard()));
|
call_args.push_back(param->get_value(get_scene_root(), get_blackboard()));
|
||||||
argptrs[i + int(include_delta)] = &call_args[i];
|
argptrs[i + int(include_delta)] = &call_args[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ BT::Status BTCallMethod::_tick(double p_delta) {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < args.size(); i++) {
|
for (int i = 0; i < args.size(); i++) {
|
||||||
Ref<BBVariant> param = args[i];
|
Ref<BBVariant> param = args[i];
|
||||||
call_args.push_back(param->get_value(get_agent(), get_blackboard()));
|
call_args.push_back(param->get_value(get_scene_root(), get_blackboard()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Unsure how to detect call error, so we return SUCCESS for now...
|
// TODO: Unsure how to detect call error, so we return SUCCESS for now...
|
||||||
|
|
|
@ -107,7 +107,7 @@ String BTEvaluateExpression::_generate_name() {
|
||||||
BT::Status BTEvaluateExpression::_tick(double p_delta) {
|
BT::Status BTEvaluateExpression::_tick(double p_delta) {
|
||||||
ERR_FAIL_COND_V_MSG(expression_string.is_empty(), FAILURE, "BTEvaluateExpression: Expression String is not set.");
|
ERR_FAIL_COND_V_MSG(expression_string.is_empty(), FAILURE, "BTEvaluateExpression: Expression String is not set.");
|
||||||
ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTEvaluateExpression: Node parameter is not set.");
|
ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTEvaluateExpression: Node parameter is not set.");
|
||||||
Object *obj = node_param->get_value(get_agent(), get_blackboard());
|
Object *obj = node_param->get_value(get_scene_root(), get_blackboard());
|
||||||
ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTEvaluateExpression: Failed to get object: " + node_param->to_string());
|
ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTEvaluateExpression: Failed to get object: " + node_param->to_string());
|
||||||
ERR_FAIL_COND_V_MSG(is_parsed != Error::OK, FAILURE, "BTEvaluateExpression: Failed to parse expression: " + expression.get_error_text());
|
ERR_FAIL_COND_V_MSG(is_parsed != Error::OK, FAILURE, "BTEvaluateExpression: Failed to parse expression: " + expression.get_error_text());
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ BT::Status BTEvaluateExpression::_tick(double p_delta) {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < input_values.size(); ++i) {
|
for (int i = 0; i < input_values.size(); ++i) {
|
||||||
const Ref<BBVariant> &bb_variant = input_values[i];
|
const Ref<BBVariant> &bb_variant = input_values[i];
|
||||||
processed_input_values[i + int(input_include_delta)] = bb_variant->get_value(get_agent(), get_blackboard());
|
processed_input_values[i + int(input_include_delta)] = bb_variant->get_value(get_scene_root(), get_blackboard());
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant result = expression.execute(processed_input_values, obj, false);
|
Variant result = expression.execute(processed_input_values, obj, false);
|
||||||
|
|
|
@ -19,6 +19,8 @@ class BTFail : public BTAction {
|
||||||
TASK_CATEGORY(Utility);
|
TASK_CATEGORY(Utility);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,6 @@ func _init_state_machine() -> void:
|
||||||
|
|
||||||
hsm.initialize(self)
|
hsm.initialize(self)
|
||||||
hsm.set_active(true)
|
hsm.set_active(true)
|
||||||
hsm.set_guard(_can_dodge)
|
|
||||||
|
|
||||||
|
|
||||||
func _init_input_events() -> void:
|
func _init_input_events() -> void:
|
||||||
|
|
|
@ -49,11 +49,11 @@ Methods
|
||||||
.. table::
|
.. table::
|
||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
+-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`Variant.Type<enum_@GlobalScope_Variant.Type>` | :ref:`get_type<class_BBParam_method_get_type>` **(** **)** |const| |
|
| :ref:`Variant.Type<enum_@GlobalScope_Variant.Type>` | :ref:`get_type<class_BBParam_method_get_type>` **(** **)** |const| |
|
||||||
+-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| Variant | :ref:`get_value<class_BBParam_method_get_value>` **(** Object agent, :ref:`Blackboard<class_Blackboard>` blackboard, Variant default=null **)** |
|
| Variant | :ref:`get_value<class_BBParam_method_get_value>` **(** Node scene_root, :ref:`Blackboard<class_Blackboard>` blackboard, Variant default=null **)** |
|
||||||
+-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
.. rst-class:: classref-section-separator
|
.. rst-class:: classref-section-separator
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ Returns the expected data type of the parameter.
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
Variant **get_value** **(** Object agent, :ref:`Blackboard<class_Blackboard>` blackboard, Variant default=null **)**
|
Variant **get_value** **(** Node scene_root, :ref:`Blackboard<class_Blackboard>` blackboard, Variant default=null **)**
|
||||||
|
|
||||||
Returns the value of the parameter.
|
Returns the value of the parameter.
|
||||||
|
|
||||||
|
|
|
@ -55,17 +55,17 @@ Methods
|
||||||
.. table::
|
.. table::
|
||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BehaviorTree<class_BehaviorTree>` | :ref:`clone<class_BehaviorTree_method_clone>` **(** **)** |const| |
|
| :ref:`BehaviorTree<class_BehaviorTree>` | :ref:`clone<class_BehaviorTree_method_clone>` **(** **)** |const| |
|
||||||
+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`copy_other<class_BehaviorTree_method_copy_other>` **(** :ref:`BehaviorTree<class_BehaviorTree>` other **)** |
|
| void | :ref:`copy_other<class_BehaviorTree_method_copy_other>` **(** :ref:`BehaviorTree<class_BehaviorTree>` other **)** |
|
||||||
+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`get_root_task<class_BehaviorTree_method_get_root_task>` **(** **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`get_root_task<class_BehaviorTree_method_get_root_task>` **(** **)** |const| |
|
||||||
+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`instantiate<class_BehaviorTree_method_instantiate>` **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`instantiate<class_BehaviorTree_method_instantiate>` **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard, Node scene_root **)** |const| |
|
||||||
+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`set_root_task<class_BehaviorTree_method_set_root_task>` **(** :ref:`BTTask<class_BTTask>` task **)** |
|
| void | :ref:`set_root_task<class_BehaviorTree_method_set_root_task>` **(** :ref:`BTTask<class_BTTask>` task **)** |
|
||||||
+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
.. rst-class:: classref-section-separator
|
.. rst-class:: classref-section-separator
|
||||||
|
|
||||||
|
@ -172,9 +172,9 @@ Returns the root task of the BehaviorTree resource.
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
:ref:`BTTask<class_BTTask>` **instantiate** **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard **)** |const|
|
:ref:`BTTask<class_BTTask>` **instantiate** **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard, Node scene_root **)** |const|
|
||||||
|
|
||||||
Instantiates the Behavior Tree and returns the root :ref:`BTTask<class_BTTask>`.
|
Instantiates the behavior tree and returns the root :ref:`BTTask<class_BTTask>`. ``scene_root`` should be the root node of the scene that the Behavior Tree will be used in (e.g., the owner of the node that contains the behavior tree).
|
||||||
|
|
||||||
.. rst-class:: classref-item-separator
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
|
|
@ -33,27 +33,35 @@ Methods
|
||||||
.. table::
|
.. table::
|
||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`bind_var_to_property<class_Blackboard_method_bind_var_to_property>` **(** StringName var_name, Object object, StringName property, bool create **)** |
|
| void | :ref:`bind_var_to_property<class_Blackboard_method_bind_var_to_property>` **(** StringName var_name, Object object, StringName property, bool create=false **)** |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| void | :ref:`clear<class_Blackboard_method_clear>` **(** **)** |
|
||||||
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`erase_var<class_Blackboard_method_erase_var>` **(** StringName var_name **)** |
|
| void | :ref:`erase_var<class_Blackboard_method_erase_var>` **(** StringName var_name **)** |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`Blackboard<class_Blackboard>` | :ref:`get_parent<class_Blackboard_method_get_parent>` **(** **)** |const| |
|
| :ref:`Blackboard<class_Blackboard>` | :ref:`get_parent<class_Blackboard_method_get_parent>` **(** **)** |const| |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| Variant | :ref:`get_var<class_Blackboard_method_get_var>` **(** StringName var_name, Variant default=null, bool complain=true **)** |const| |
|
| Variant | :ref:`get_var<class_Blackboard_method_get_var>` **(** StringName var_name, Variant default=null, bool complain=true **)** |const| |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| Dictionary | :ref:`get_vars_as_dict<class_Blackboard_method_get_vars_as_dict>` **(** **)** |const| |
|
||||||
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| bool | :ref:`has_var<class_Blackboard_method_has_var>` **(** StringName var_name **)** |const| |
|
| bool | :ref:`has_var<class_Blackboard_method_has_var>` **(** StringName var_name **)** |const| |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`link_var<class_Blackboard_method_link_var>` **(** StringName var_name, :ref:`Blackboard<class_Blackboard>` target_blackboard, StringName target_var, bool create **)** |
|
| void | :ref:`link_var<class_Blackboard_method_link_var>` **(** StringName var_name, :ref:`Blackboard<class_Blackboard>` target_blackboard, StringName target_var, bool create=false **)** |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| StringName[] | :ref:`list_vars<class_Blackboard_method_list_vars>` **(** **)** |const| |
|
||||||
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| void | :ref:`populate_from_dict<class_Blackboard_method_populate_from_dict>` **(** Dictionary dictionary **)** |
|
||||||
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`set_parent<class_Blackboard_method_set_parent>` **(** :ref:`Blackboard<class_Blackboard>` blackboard **)** |
|
| void | :ref:`set_parent<class_Blackboard_method_set_parent>` **(** :ref:`Blackboard<class_Blackboard>` blackboard **)** |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`set_var<class_Blackboard_method_set_var>` **(** StringName var_name, Variant value **)** |
|
| void | :ref:`set_var<class_Blackboard_method_set_var>` **(** StringName var_name, Variant value **)** |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`Blackboard<class_Blackboard>` | :ref:`top<class_Blackboard_method_top>` **(** **)** |const| |
|
| :ref:`Blackboard<class_Blackboard>` | :ref:`top<class_Blackboard_method_top>` **(** **)** |const| |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`unbind_var<class_Blackboard_method_unbind_var>` **(** StringName var_name **)** |
|
| void | :ref:`unbind_var<class_Blackboard_method_unbind_var>` **(** StringName var_name **)** |
|
||||||
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
.. rst-class:: classref-section-separator
|
.. rst-class:: classref-section-separator
|
||||||
|
|
||||||
|
@ -68,7 +76,7 @@ Method Descriptions
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
void **bind_var_to_property** **(** StringName var_name, Object object, StringName property, bool create **)**
|
void **bind_var_to_property** **(** StringName var_name, Object object, StringName property, bool create=false **)**
|
||||||
|
|
||||||
Establish a binding between a variable and the object's property specified by ``property`` and ``object``. Changes to the variable update the property, and vice versa. If ``create`` is ``true``, the variable will be created if it doesn't exist.
|
Establish a binding between a variable and the object's property specified by ``property`` and ``object``. Changes to the variable update the property, and vice versa. If ``create`` is ``true``, the variable will be created if it doesn't exist.
|
||||||
|
|
||||||
|
@ -76,6 +84,18 @@ Establish a binding between a variable and the object's property specified by ``
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_Blackboard_method_clear:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
void **clear** **(** **)**
|
||||||
|
|
||||||
|
Removes all variables from the Blackboard. Parent scopes are not affected.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_Blackboard_method_erase_var:
|
.. _class_Blackboard_method_erase_var:
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
@ -112,6 +132,18 @@ Returns variable value or ``default`` if variable doesn't exist. If ``complain``
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_Blackboard_method_get_vars_as_dict:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
Dictionary **get_vars_as_dict** **(** **)** |const|
|
||||||
|
|
||||||
|
Returns all variables in the Blackboard as a dictionary. Keys are the variable names, values are the variable values. Parent scopes are not included.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_Blackboard_method_has_var:
|
.. _class_Blackboard_method_has_var:
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
@ -128,7 +160,7 @@ Returns ``true`` if the Blackboard contains the ``var_name`` variable, including
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
void **link_var** **(** StringName var_name, :ref:`Blackboard<class_Blackboard>` target_blackboard, StringName target_var, bool create **)**
|
void **link_var** **(** StringName var_name, :ref:`Blackboard<class_Blackboard>` target_blackboard, StringName target_var, bool create=false **)**
|
||||||
|
|
||||||
Links a variable to another Blackboard variable. If a variable is linked to another variable, their state will always be identical, and any change to one will be reflected in the other. If ``create`` is ``true``, the variable will be created if it doesn't exist.
|
Links a variable to another Blackboard variable. If a variable is linked to another variable, their state will always be identical, and any change to one will be reflected in the other. If ``create`` is ``true``, the variable will be created if it doesn't exist.
|
||||||
|
|
||||||
|
@ -138,6 +170,30 @@ You can use this method to link a variable in the current scope to a variable in
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_Blackboard_method_list_vars:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
StringName[] **list_vars** **(** **)** |const|
|
||||||
|
|
||||||
|
Returns all variable names in the Blackboard. Parent scopes are not included.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
.. _class_Blackboard_method_populate_from_dict:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
void **populate_from_dict** **(** Dictionary dictionary **)**
|
||||||
|
|
||||||
|
Fills the Blackboard with multiple variables from a dictionary. The dictionary keys must be variable names and the dictionary values must be variable values. Keys must be StringName or String.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_Blackboard_method_set_parent:
|
.. _class_Blackboard_method_set_parent:
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
|
@ -35,16 +35,20 @@ Methods
|
||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`Blackboard<class_Blackboard>` | :ref:`create_blackboard<class_BlackboardPlan_method_create_blackboard>` **(** Node node **)** |
|
| :ref:`Blackboard<class_Blackboard>` | :ref:`create_blackboard<class_BlackboardPlan_method_create_blackboard>` **(** Node node, :ref:`Blackboard<class_Blackboard>` parent_scope=null **)** |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BlackboardPlan<class_BlackboardPlan>` | :ref:`get_base_plan<class_BlackboardPlan_method_get_base_plan>` **(** **)** |const| |
|
| :ref:`BlackboardPlan<class_BlackboardPlan>` | :ref:`get_base_plan<class_BlackboardPlan_method_get_base_plan>` **(** **)** |const| |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| Callable | :ref:`get_parent_scope_plan_provider<class_BlackboardPlan_method_get_parent_scope_plan_provider>` **(** **)** |const| |
|
||||||
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| bool | :ref:`is_derived<class_BlackboardPlan_method_is_derived>` **(** **)** |const| |
|
| bool | :ref:`is_derived<class_BlackboardPlan_method_is_derived>` **(** **)** |const| |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`populate_blackboard<class_BlackboardPlan_method_populate_blackboard>` **(** :ref:`Blackboard<class_Blackboard>` blackboard, bool overwrite, Node node **)** |
|
| void | :ref:`populate_blackboard<class_BlackboardPlan_method_populate_blackboard>` **(** :ref:`Blackboard<class_Blackboard>` blackboard, bool overwrite, Node node **)** |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`set_base_plan<class_BlackboardPlan_method_set_base_plan>` **(** :ref:`BlackboardPlan<class_BlackboardPlan>` blackboard_plan **)** |
|
| void | :ref:`set_base_plan<class_BlackboardPlan_method_set_base_plan>` **(** :ref:`BlackboardPlan<class_BlackboardPlan>` blackboard_plan **)** |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| void | :ref:`set_parent_scope_plan_provider<class_BlackboardPlan_method_set_parent_scope_plan_provider>` **(** Callable callable **)** |
|
||||||
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`sync_with_base_plan<class_BlackboardPlan_method_sync_with_base_plan>` **(** **)** |
|
| void | :ref:`sync_with_base_plan<class_BlackboardPlan_method_sync_with_base_plan>` **(** **)** |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
@ -83,7 +87,7 @@ Method Descriptions
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
:ref:`Blackboard<class_Blackboard>` **create_blackboard** **(** Node node **)**
|
:ref:`Blackboard<class_Blackboard>` **create_blackboard** **(** Node node, :ref:`Blackboard<class_Blackboard>` parent_scope=null **)**
|
||||||
|
|
||||||
Constructs a new instance of a :ref:`Blackboard<class_Blackboard>` using this plan. If ``NodePath`` prefetching is enabled, ``node`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values.
|
Constructs a new instance of a :ref:`Blackboard<class_Blackboard>` using this plan. If ``NodePath`` prefetching is enabled, ``node`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values.
|
||||||
|
|
||||||
|
@ -103,6 +107,18 @@ Returns the base plan. See :ref:`is_derived<class_BlackboardPlan_method_is_deriv
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_BlackboardPlan_method_get_parent_scope_plan_provider:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
Callable **get_parent_scope_plan_provider** **(** **)** |const|
|
||||||
|
|
||||||
|
Returns the parent scope plan provider - a callable that returns a **BlackboardPlan**.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_BlackboardPlan_method_is_derived:
|
.. _class_BlackboardPlan_method_is_derived:
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
@ -141,6 +157,18 @@ Use with caution, as it will remove variables not present in the base plan. Only
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_BlackboardPlan_method_set_parent_scope_plan_provider:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
void **set_parent_scope_plan_provider** **(** Callable callable **)**
|
||||||
|
|
||||||
|
Sets the parent scope plan provider - a callable that returns a **BlackboardPlan**. Used to provide hints in the inspector. When set, mapping feature becomes available.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_BlackboardPlan_method_sync_with_base_plan:
|
.. _class_BlackboardPlan_method_sync_with_base_plan:
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
|
@ -19,7 +19,7 @@ Player of :ref:`BehaviorTree<class_BehaviorTree>` resources.
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
BTPlayer node is used for the instantiation and playback of :ref:`BehaviorTree<class_BehaviorTree>` resources at runtime. During instantiation, the behavior tree instance is initialized with a reference to the agent and the :ref:`blackboard<class_BTPlayer_property_blackboard>`. Agent is the owner of the BTPlayer node (see :ref:`Node.owner<class_Node_member_owner>`).
|
**BTPlayer** node is used to instantiate and play :ref:`BehaviorTree<class_BehaviorTree>` resources at runtime. During initialization, the behavior tree instance is given references to the agent, the :ref:`blackboard<class_BTPlayer_property_blackboard>`, and the current scene root. The agent can be specified by the :ref:`agent_node<class_BTPlayer_property_agent_node>` property (defaults to the BTPlayer's parent node).
|
||||||
|
|
||||||
For an introduction to behavior trees, see :ref:`BehaviorTree<class_BehaviorTree>`.
|
For an introduction to behavior trees, see :ref:`BehaviorTree<class_BehaviorTree>`.
|
||||||
|
|
||||||
|
@ -31,19 +31,21 @@ Properties
|
||||||
.. table::
|
.. table::
|
||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
| bool | :ref:`active<class_BTPlayer_property_active>` | ``true`` |
|
| bool | :ref:`active<class_BTPlayer_property_active>` | ``true`` |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
|
| NodePath | :ref:`agent_node<class_BTPlayer_property_agent_node>` | ``NodePath("..")`` |
|
||||||
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
| :ref:`BehaviorTree<class_BehaviorTree>` | :ref:`behavior_tree<class_BTPlayer_property_behavior_tree>` | |
|
| :ref:`BehaviorTree<class_BehaviorTree>` | :ref:`behavior_tree<class_BTPlayer_property_behavior_tree>` | |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
| :ref:`Blackboard<class_Blackboard>` | :ref:`blackboard<class_BTPlayer_property_blackboard>` | |
|
| :ref:`Blackboard<class_Blackboard>` | :ref:`blackboard<class_BTPlayer_property_blackboard>` | |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
| :ref:`BlackboardPlan<class_BlackboardPlan>` | :ref:`blackboard_plan<class_BTPlayer_property_blackboard_plan>` | |
|
| :ref:`BlackboardPlan<class_BlackboardPlan>` | :ref:`blackboard_plan<class_BTPlayer_property_blackboard_plan>` | |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
| bool | :ref:`monitor_performance<class_BTPlayer_property_monitor_performance>` | ``false`` |
|
| bool | :ref:`monitor_performance<class_BTPlayer_property_monitor_performance>` | ``false`` |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
| :ref:`UpdateMode<enum_BTPlayer_UpdateMode>` | :ref:`update_mode<class_BTPlayer_property_update_mode>` | ``1`` |
|
| :ref:`UpdateMode<enum_BTPlayer_UpdateMode>` | :ref:`update_mode<class_BTPlayer_property_update_mode>` | ``1`` |
|
||||||
+---------------------------------------------+-------------------------------------------------------------------------+-----------+
|
+---------------------------------------------+-------------------------------------------------------------------------+--------------------+
|
||||||
|
|
||||||
.. rst-class:: classref-reftable-group
|
.. rst-class:: classref-reftable-group
|
||||||
|
|
||||||
|
@ -161,6 +163,23 @@ If ``true``, the behavior tree will be executed during update.
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_BTPlayer_property_agent_node:
|
||||||
|
|
||||||
|
.. rst-class:: classref-property
|
||||||
|
|
||||||
|
NodePath **agent_node** = ``NodePath("..")``
|
||||||
|
|
||||||
|
.. rst-class:: classref-property-setget
|
||||||
|
|
||||||
|
- void **set_agent_node** **(** NodePath value **)**
|
||||||
|
- NodePath **get_agent_node** **(** **)**
|
||||||
|
|
||||||
|
Path to the node that will be used as the agent. Setting it after instantiation will have no effect.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_BTPlayer_property_behavior_tree:
|
.. _class_BTPlayer_property_behavior_tree:
|
||||||
|
|
||||||
.. rst-class:: classref-property
|
.. rst-class:: classref-property
|
||||||
|
|
|
@ -23,6 +23,8 @@ BTSubtree instantiates a :ref:`BehaviorTree<class_BehaviorTree>` and includes it
|
||||||
|
|
||||||
Returns the status of the subtree's execution.
|
Returns the status of the subtree's execution.
|
||||||
|
|
||||||
|
Subtree blackboard variables can be mapped to the main tree blackboard plan variables. Check out mapping section in the inspector.
|
||||||
|
|
||||||
Note: BTSubTree is designed as a simpler loader, and does not support updating :ref:`subtree<class_BTSubtree_property_subtree>` at runtime. A custom subtree decorator is better suited and `somewhat trivial <https://github.com/limbonaut/limboai/issues/94#issuecomment-2068833610>`__ to implement.
|
Note: BTSubTree is designed as a simpler loader, and does not support updating :ref:`subtree<class_BTSubtree_property_subtree>` at runtime. A custom subtree decorator is better suited and `somewhat trivial <https://github.com/limbonaut/limboai/issues/94#issuecomment-2068833610>`__ to implement.
|
||||||
|
|
||||||
.. rst-class:: classref-reftable-group
|
.. rst-class:: classref-reftable-group
|
||||||
|
|
|
@ -46,6 +46,8 @@ Properties
|
||||||
+-------------------------------------+---------------------------------------------------------+--------+
|
+-------------------------------------+---------------------------------------------------------+--------+
|
||||||
| float | :ref:`elapsed_time<class_BTTask_property_elapsed_time>` | |
|
| float | :ref:`elapsed_time<class_BTTask_property_elapsed_time>` | |
|
||||||
+-------------------------------------+---------------------------------------------------------+--------+
|
+-------------------------------------+---------------------------------------------------------+--------+
|
||||||
|
| Node | :ref:`scene_root<class_BTTask_property_scene_root>` | |
|
||||||
|
+-------------------------------------+---------------------------------------------------------+--------+
|
||||||
| :ref:`Status<enum_BT_Status>` | :ref:`status<class_BTTask_property_status>` | |
|
| :ref:`Status<enum_BT_Status>` | :ref:`status<class_BTTask_property_status>` | |
|
||||||
+-------------------------------------+---------------------------------------------------------+--------+
|
+-------------------------------------+---------------------------------------------------------+--------+
|
||||||
|
|
||||||
|
@ -57,59 +59,61 @@ Methods
|
||||||
.. table::
|
.. table::
|
||||||
:widths: auto
|
:widths: auto
|
||||||
|
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`_enter<class_BTTask_private_method__enter>` **(** **)** |virtual| |
|
| void | :ref:`_enter<class_BTTask_private_method__enter>` **(** **)** |virtual| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`_exit<class_BTTask_private_method__exit>` **(** **)** |virtual| |
|
| void | :ref:`_exit<class_BTTask_private_method__exit>` **(** **)** |virtual| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| String | :ref:`_generate_name<class_BTTask_private_method__generate_name>` **(** **)** |virtual| |const| |
|
| String | :ref:`_generate_name<class_BTTask_private_method__generate_name>` **(** **)** |virtual| |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| PackedStringArray | :ref:`_get_configuration_warnings<class_BTTask_private_method__get_configuration_warnings>` **(** **)** |virtual| |const| |
|
| PackedStringArray | :ref:`_get_configuration_warnings<class_BTTask_private_method__get_configuration_warnings>` **(** **)** |virtual| |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`_setup<class_BTTask_private_method__setup>` **(** **)** |virtual| |
|
| void | :ref:`_setup<class_BTTask_private_method__setup>` **(** **)** |virtual| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`Status<enum_BT_Status>` | :ref:`_tick<class_BTTask_private_method__tick>` **(** float delta **)** |virtual| |
|
| :ref:`Status<enum_BT_Status>` | :ref:`_tick<class_BTTask_private_method__tick>` **(** float delta **)** |virtual| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`abort<class_BTTask_method_abort>` **(** **)** |
|
| void | :ref:`abort<class_BTTask_method_abort>` **(** **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`add_child<class_BTTask_method_add_child>` **(** :ref:`BTTask<class_BTTask>` task **)** |
|
| void | :ref:`add_child<class_BTTask_method_add_child>` **(** :ref:`BTTask<class_BTTask>` task **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`add_child_at_index<class_BTTask_method_add_child_at_index>` **(** :ref:`BTTask<class_BTTask>` task, int idx **)** |
|
| void | :ref:`add_child_at_index<class_BTTask_method_add_child_at_index>` **(** :ref:`BTTask<class_BTTask>` task, int idx **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`clone<class_BTTask_method_clone>` **(** **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`clone<class_BTTask_method_clone>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| :ref:`BehaviorTree<class_BehaviorTree>` | :ref:`editor_get_behavior_tree<class_BTTask_method_editor_get_behavior_tree>` **(** **)** |
|
||||||
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`Status<enum_BT_Status>` | :ref:`execute<class_BTTask_method_execute>` **(** float delta **)** |
|
| :ref:`Status<enum_BT_Status>` | :ref:`execute<class_BTTask_method_execute>` **(** float delta **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`get_child<class_BTTask_method_get_child>` **(** int idx **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`get_child<class_BTTask_method_get_child>` **(** int idx **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| int | :ref:`get_child_count<class_BTTask_method_get_child_count>` **(** **)** |const| |
|
| int | :ref:`get_child_count<class_BTTask_method_get_child_count>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| int | :ref:`get_child_count_excluding_comments<class_BTTask_method_get_child_count_excluding_comments>` **(** **)** |const| |
|
| int | :ref:`get_child_count_excluding_comments<class_BTTask_method_get_child_count_excluding_comments>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| int | :ref:`get_index<class_BTTask_method_get_index>` **(** **)** |const| |
|
| int | :ref:`get_index<class_BTTask_method_get_index>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`get_parent<class_BTTask_method_get_parent>` **(** **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`get_parent<class_BTTask_method_get_parent>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`get_root<class_BTTask_method_get_root>` **(** **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`get_root<class_BTTask_method_get_root>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| String | :ref:`get_task_name<class_BTTask_method_get_task_name>` **(** **)** |
|
| String | :ref:`get_task_name<class_BTTask_method_get_task_name>` **(** **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| bool | :ref:`has_child<class_BTTask_method_has_child>` **(** :ref:`BTTask<class_BTTask>` task **)** |const| |
|
| bool | :ref:`has_child<class_BTTask_method_has_child>` **(** :ref:`BTTask<class_BTTask>` task **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`initialize<class_BTTask_method_initialize>` **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard **)** |
|
| void | :ref:`initialize<class_BTTask_method_initialize>` **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard, Node scene_root **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| bool | :ref:`is_descendant_of<class_BTTask_method_is_descendant_of>` **(** :ref:`BTTask<class_BTTask>` task **)** |const| |
|
| bool | :ref:`is_descendant_of<class_BTTask_method_is_descendant_of>` **(** :ref:`BTTask<class_BTTask>` task **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| bool | :ref:`is_root<class_BTTask_method_is_root>` **(** **)** |const| |
|
| bool | :ref:`is_root<class_BTTask_method_is_root>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| :ref:`BTTask<class_BTTask>` | :ref:`next_sibling<class_BTTask_method_next_sibling>` **(** **)** |const| |
|
| :ref:`BTTask<class_BTTask>` | :ref:`next_sibling<class_BTTask_method_next_sibling>` **(** **)** |const| |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`print_tree<class_BTTask_method_print_tree>` **(** int initial_tabs=0 **)** |
|
| void | :ref:`print_tree<class_BTTask_method_print_tree>` **(** int initial_tabs=0 **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`remove_child<class_BTTask_method_remove_child>` **(** :ref:`BTTask<class_BTTask>` task **)** |
|
| void | :ref:`remove_child<class_BTTask_method_remove_child>` **(** :ref:`BTTask<class_BTTask>` task **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| void | :ref:`remove_child_at_index<class_BTTask_method_remove_child_at_index>` **(** int idx **)** |
|
| void | :ref:`remove_child_at_index<class_BTTask_method_remove_child_at_index>` **(** int idx **)** |
|
||||||
+-------------------------------+---------------------------------------------------------------------------------------------------------------------------+
|
+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
.. rst-class:: classref-section-separator
|
.. rst-class:: classref-section-separator
|
||||||
|
|
||||||
|
@ -131,7 +135,7 @@ Node **agent**
|
||||||
- void **set_agent** **(** Node value **)**
|
- void **set_agent** **(** Node value **)**
|
||||||
- Node **get_agent** **(** **)**
|
- Node **get_agent** **(** **)**
|
||||||
|
|
||||||
The agent is a contextual object for the task's :ref:`BehaviorTree<class_BehaviorTree>` instance. Usually, agent is the owner of the :ref:`BTPlayer<class_BTPlayer>` node containing the :ref:`BehaviorTree<class_BehaviorTree>` resource.
|
The agent is the contextual object for the :ref:`BehaviorTree<class_BehaviorTree>` instance. This is usually the parent of the :ref:`BTPlayer<class_BTPlayer>` node that utilizes the :ref:`BehaviorTree<class_BehaviorTree>` resource.
|
||||||
|
|
||||||
.. rst-class:: classref-item-separator
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
@ -190,6 +194,33 @@ Returns ``0`` when task is not ``RUNNING``.
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_BTTask_property_scene_root:
|
||||||
|
|
||||||
|
.. rst-class:: classref-property
|
||||||
|
|
||||||
|
Node **scene_root**
|
||||||
|
|
||||||
|
.. rst-class:: classref-property-setget
|
||||||
|
|
||||||
|
- Node **get_scene_root** **(** **)**
|
||||||
|
|
||||||
|
Root node of the scene the behavior tree is used in (e.g., the owner of the :ref:`BTPlayer<class_BTPlayer>` node). Can be uses to retrieve ``NodePath`` references.
|
||||||
|
|
||||||
|
\ **Example:**\
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
extends BTAction
|
||||||
|
|
||||||
|
@export var node_path: NodePath
|
||||||
|
|
||||||
|
func _setup():
|
||||||
|
var node: Node = scene_root.get_node(node_path)
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_BTTask_property_status:
|
.. _class_BTTask_property_status:
|
||||||
|
|
||||||
.. rst-class:: classref-property
|
.. rst-class:: classref-property
|
||||||
|
@ -337,6 +368,18 @@ Duplicates the task and its children, copying the exported members. Sub-resource
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.. _class_BTTask_method_editor_get_behavior_tree:
|
||||||
|
|
||||||
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
|
:ref:`BehaviorTree<class_BehaviorTree>` **editor_get_behavior_tree** **(** **)**
|
||||||
|
|
||||||
|
Returns the behavior tree that owns this task. This is only available in the editor.
|
||||||
|
|
||||||
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
.. _class_BTTask_method_execute:
|
.. _class_BTTask_method_execute:
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
@ -457,11 +500,11 @@ Returns ``true`` if ``task`` is a child of this task.
|
||||||
|
|
||||||
.. rst-class:: classref-method
|
.. rst-class:: classref-method
|
||||||
|
|
||||||
void **initialize** **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard **)**
|
void **initialize** **(** Node agent, :ref:`Blackboard<class_Blackboard>` blackboard, Node scene_root **)**
|
||||||
|
|
||||||
Initilizes the task. Assigns :ref:`agent<class_BTTask_property_agent>` and :ref:`blackboard<class_BTTask_property_blackboard>`, and calls :ref:`_setup<class_BTTask_private_method__setup>` for the task and its children.
|
Initilizes the task. Assigns :ref:`agent<class_BTTask_property_agent>` and :ref:`blackboard<class_BTTask_property_blackboard>`, and calls :ref:`_setup<class_BTTask_private_method__setup>` for the task and its children.
|
||||||
|
|
||||||
The method is called recursively for each child task.
|
The method is called recursively for each child task. ``scene_root`` should be the root node of the scene the behavior tree is used in (e.g., the owner of the node that contains the behavior tree).
|
||||||
|
|
||||||
.. rst-class:: classref-item-separator
|
.. rst-class:: classref-item-separator
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
Accessing nodes in the scene tree
|
Accessing nodes in the scene tree
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
There are several ways to access nodes in the agent's scene tree.
|
There are several ways to access nodes in the agent's scene tree from a :ref:`BTTask<class_BTTask>`.
|
||||||
|
|
||||||
**🛈 Note:** Agent is the owner of :ref:`BTPlayer<class_BTPlayer>` node.
|
**🛈 Note:** The root node of the agent's scene tree can be accessed with the
|
||||||
|
:ref:`scene_root<class_BTTask_property_scene_root>` property.
|
||||||
|
|
||||||
|
|
||||||
With ``BBNode`` property
|
With ``BBNode`` property
|
||||||
|
@ -16,7 +17,7 @@ With ``BBNode`` property
|
||||||
@export var cast_param: BBNode
|
@export var cast_param: BBNode
|
||||||
|
|
||||||
func _tick(delta) -> Status:
|
func _tick(delta) -> Status:
|
||||||
var node: ShapeCast3D = cast_param.get_value(agent, blackboard)
|
var node: ShapeCast3D = cast_param.get_value(scene_root, blackboard)
|
||||||
|
|
||||||
|
|
||||||
With ``NodePath`` property
|
With ``NodePath`` property
|
||||||
|
@ -27,14 +28,16 @@ With ``NodePath`` property
|
||||||
@export var cast_path: NodePath
|
@export var cast_path: NodePath
|
||||||
|
|
||||||
func _tick(delta) -> Status:
|
func _tick(delta) -> Status:
|
||||||
var node: ShapeCast3D = agent.get_node(cast_path)
|
var node: ShapeCast3D = scene_root.get_node(cast_path)
|
||||||
|
|
||||||
|
|
||||||
Using blackboard plan
|
Using blackboard plan
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
You can :ref:`create a blackboard variable<editing_plan>` in the editor with the type ``NodePath``
|
You can :ref:`create a blackboard variable<editing_plan>` in the editor with the type ``NodePath``
|
||||||
and point it to the proper node in the :ref:`BTPlayer<class_BTPlayer>` blackboard plan.
|
and point it to the proper node in the :ref:`BTPlayer<class_BTPlayer>` blackboard plan. By default,
|
||||||
|
any ``NodePath`` variable will be replaced with the node instance when the blackboard is instantiated
|
||||||
|
at runtime (see :ref:`BlackboardPlan.prefetch_nodepath_vars<class_BlackboardPlan_property_prefetch_nodepath_vars>`).
|
||||||
|
|
||||||
.. code:: gdscript
|
.. code:: gdscript
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ Example 1: A simple action
|
||||||
|
|
||||||
# Called each time this task is ticked (aka executed).
|
# Called each time this task is ticked (aka executed).
|
||||||
func _tick(p_delta: float) -> Status:
|
func _tick(p_delta: float) -> Status:
|
||||||
var n: CanvasItem = agent.get_node_or_null(node_path)
|
var n: CanvasItem = scene_root.get_node_or_null(node_path)
|
||||||
if is_instance_valid(n):
|
if is_instance_valid(n):
|
||||||
n.visible = visible
|
n.visible = visible
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
|
|
|
@ -91,7 +91,7 @@ Usage example:
|
||||||
@export var speed: BBFloat
|
@export var speed: BBFloat
|
||||||
|
|
||||||
func _tick(delta: float) -> Status:
|
func _tick(delta: float) -> Status:
|
||||||
var current_speed: float = speed.get_value(agent, blackboard, 0.0)
|
var current_speed: float = speed.get_value(scene_root, blackboard, 0.0)
|
||||||
...
|
...
|
||||||
|
|
||||||
Advanced topic: Blackboard scopes
|
Advanced topic: Blackboard scopes
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue