Compare commits

..

156 Commits

Author SHA1 Message Date
Serhii Snitsaruk 0f3d743f68
Merge ee8c773e71 into eaa43020f5 2024-10-16 12:32:30 +00:00
Serhii Snitsaruk ee8c773e71
GHA: Build with ios_simulator=yes flag 2024-10-16 14:32:39 +02:00
Serhii Snitsaruk 7f38fe2b8b
GHA: Change iOS arch to arm64 & build simulator libs 2024-10-16 14:32:39 +02:00
Serhii Snitsaruk 500775eb14
Add iOS builds to the GDExtension manifest 2024-10-16 14:32:39 +02:00
Serhii Snitsaruk 1cdde4d5a9
GHA: Add iOS builds to GDExtension workflow 2024-10-16 14:31:56 +02:00
Serhii Snitsaruk eaa43020f5
Merge pull request #235 from limbonaut/doc-get-var-fix
Doc: Clarify `Blackboard.get_var()` and `set_var()`
2024-10-13 12:27:12 -07:00
Serhii Snitsaruk b5b1ac7289
Doc: Clarify `Blackboard.get_var()` and `set_var()` 2024-10-13 21:04:59 +02:00
Serhii Snitsaruk ece17d68d9
Merge pull request #234 from limbonaut/doc-fixes
GHA: Code style checks for PRs and commits
2024-10-13 12:03:17 -07:00
Serhii Snitsaruk 85787616e7
GHA: Add code style check for PRs and direct commits 2024-10-13 20:43:59 +02:00
Serhii Snitsaruk 11abf36c99
Clang format 2024-10-13 20:25:03 +02:00
Serhii Snitsaruk 19d771fef2
Merge pull request #229 from monxa/tasktree-search
Implement Tree Search Functionality with Highlighting and Filtering
2024-10-13 11:18:37 -07:00
Serhii Snitsaruk 2b89d1d23e
Merge pull request #233 from limbonaut/gha-fix-macos-vulkan
GHA: Fix Vulkan SDK installation step
2024-10-13 10:48:31 -07:00
Serhii Snitsaruk 6f318b83b8
GHA: Fix Vulkan SDK installation step 2024-10-13 18:25:54 +02:00
Serhii Snitsaruk 7a1b56f9c8
GHA: Switch workflows to Godot 4.3 branch 2024-10-13 17:06:25 +02:00
Alexander Montag 2b86928737
Add tooltip to explain case sensitivity behavior 2024-10-13 07:02:59 +00:00
Alexander Montag 8c557f87f7
Address 2. review for TreeSearch
Remove redundant comment

Prune tab_search_context

Fix restore tab on `_tab_closed`

Add break statement

Pass callable by reference in _draw_highlight_item

Refactor _initialize_controls into constructor

Remove redundant if (!line_edit_search)-check
2024-10-13 07:31:35 +02:00
Alexander Montag 6776319472
Implement Tree Search Functionality with Highlighting and Filtering
This commit introduces a comprehensive Tree Search feature, including:
- Tree highlighting: Highlights items that match the search query.
- Tree filtering: Filters items so only matches and descendants are
  shown.
- Counting descendants: Shows the number of matching items within collapsed branches.
- Jump to next match: on enter.
- (Limbo-)Shortcut: Default CTRL-F.
- Menu entry: Misc->Search Tree.
- Remember separate SearchInfo for each tab.

Key implementation details:
- Optimized performance for large trees
- Implemented recursive filtering for efficiency
- Added UI elements including next/previous match buttons

Development History:
- Initial implementation of highlighting and filtering
- Multiple rounds of performance optimization
- Bug fixes and refactoring for correctness
- UI enhancements and polish
- Code cleanup and style improvements
2024-10-06 06:57:11 +02:00
Serhii Snitsaruk 760af804c0
Merge pull request #230 from limbonaut/fix-docs
Fix and update docs
2024-09-30 12:36:57 +02:00
Serhii Snitsaruk c49e5142a5
Fix and update docs 2024-09-30 11:17:01 +02:00
Serhii Snitsaruk 60a767032e
Merge pull request #226 from limbonaut/fix-hsm-exit-crash
Fix invalid access errors on exit in LimboHSM
2024-09-26 16:54:31 +02:00
Serhii Snitsaruk 60142b191d
Fix invalid access crash on exit in LimboHSM
Since #131, `LimboState::_exit()` became a source of potential crashes
if object references are used without a validity check. It's too easy
to miss this, which can lead to game crashing during runtime.

This fix reverts #131 change and proposes alternative approach of
re-activating root HSM upon tree entering if it was previously active.
Note that it's not an ideal solution, as some state will be lost upon
re-parenting: HSM exits and then re-activates and enters its initial state.
2024-09-22 13:57:15 +02:00
Serhii Snitsaruk 134bb3214a
Merge pull request #225 from ydeltastar/remember-last-session
Remember loaded `BehaviorTree`s of last session
2024-09-22 13:32:56 +02:00
yds db7c990f51 Remember loaded BehaviorTrees of last session 2024-09-21 16:23:13 -03:00
Serhii Snitsaruk 08884e6180
Merge pull request #219 from monxa/fix-miscmenu-layout-duplicates
Fix duplicate entries in Misc->Layout
2024-09-17 14:42:01 +02:00
Alexander Montag c2130a7b2f Fix duplicate entries in Misc->layout
Fixes #218
2024-09-17 02:16:47 +02:00
Serhii Snitsaruk 5ddc43fe94
Merge pull request #215 from limbonaut/prefetch-with-base-plan
Prefetch nodes set directly in the BehaviorTree's BlackboardPlan
2024-09-15 17:06:55 +02:00
Serhii Snitsaruk 601aed3684
Merge pull request #216 from limbonaut/gha-debug-builds
GHA: Add an option to create GDExtension debug builds
2024-09-15 16:23:08 +02:00
Serhii Snitsaruk 0e4c06f3b8
Update class docs 2024-09-15 15:47:22 +02:00
Serhii Snitsaruk ac2d734122
Use different prefetch root for the base plan in BTPlayer and BTState 2024-09-15 15:47:11 +02:00
Serhii Snitsaruk 1ca1154cd0
Merge pull request #214 from limbonaut/fix-warnings
Fix loop variables used as copy
2024-09-15 14:36:36 +02:00
Serhii Snitsaruk a8a0f24492
BlackboardPlan: Allow passing different prefetch root for the base plan 2024-09-15 14:16:54 +02:00
Serhii Snitsaruk 50e9e570dd
Fix loop variables used as copy 2024-09-15 13:32:58 +02:00
Serhii Snitsaruk d72c2e0648
Merge pull request #213 from limbonaut/fix-setagentprop-name
Fix `BTSetAgentProperty` name generation
2024-09-14 20:23:58 +02:00
Serhii Snitsaruk da2bc5e3bb
Fix `BTSetAgentProperty` name generation 2024-09-14 19:56:31 +02:00
Serhii Snitsaruk c4481d8bed
Merge pull request #212 from limbonaut/fix-bbnode-getvalue-crash
Fix `BBNode::get_value()` crash with a freed object using GDExtension
2024-09-14 19:49:29 +02:00
Serhii Snitsaruk 689c8fab6f
Fix `BBNode::get_value()` crash with a freed object in GDExtension
It may be a bug in GDExtension. I optimized the code, and, as a workaround, removed casting to Object* from Variant. This fixed the issue. The same code worked well using module.
2024-09-14 19:30:28 +02:00
Serhii Snitsaruk fd0eb34b4e
Merge pull request #211 from limbonaut/fix-bt-for-each
Fix `BTForEach` crash if elements are removed from the array during iteration
2024-09-14 17:00:10 +02:00
Serhii Snitsaruk bfcc2f8e1b
Merge pull request #210 from ydeltastar/multi-select
Implement task multiple selection and drag and drop
2024-09-14 16:54:07 +02:00
Serhii Snitsaruk b8c9db0d44
Fix BTForEach crash if elements are removed from the array during iteration 2024-09-14 16:42:30 +02:00
yds 4df6647a75 Improve multiple drag and drop 2024-09-14 11:22:52 -03:00
Serhii Snitsaruk d78adabf7c
Bump version to 1.3-dev 2024-09-13 14:13:00 +02:00
yds 1742018696 Preserve selection after drop 2024-09-13 09:04:18 -03:00
yds a460c7898b Add drag preview 2024-09-13 09:04:18 -03:00
yds 8ee3688da2 Implement task multiple selection and drag and drop 2024-09-13 09:04:18 -03:00
Serhii Snitsaruk 9032ca0c7b
GHA: Add an option to create GDExtension debug builds 2024-09-09 13:53:42 +02:00
Serhii Snitsaruk 1cb85807dd
Fix mem leaks in the demo 2024-09-09 10:22:32 +02:00
Serhii Snitsaruk 78396708d4
Bump version to 1.2.1 2024-09-05 13:52:42 +02:00
Serhii Snitsaruk 6c86ce566c
Merge pull request #206 from limbonaut/gdextension-print-workaround
Override _to_string() to give useful info about objects in GDExtension
2024-09-05 13:48:57 +02:00
Serhii Snitsaruk 16a3bb0273
Override _to_string() to print useful info about objects in GDExtension 2024-09-05 13:39:47 +02:00
Serhii Snitsaruk ac209e7fc3
Update .gitignore 2024-09-05 11:37:18 +02:00
Serhii Snitsaruk 49b3a0ad6f
Merge pull request #205 from monxa/fix-editor-setting-gdextension
Generalize EDITOR_DEF macro to fix potential editor setting issues
2024-09-03 17:18:46 +02:00
Alexander Montag ad11f401b1 Generalize EDITOR_DEF macro to fix potential editor setting issues
This commit provides a generalized solution to ensure editor settings are
properly initialized and available in both module and GDExtension versions.
While #204 fixed the specific issue with 'limbo_ai/editor/layout', this change
aims to prevent similar problems for all editor settings.

In particular, `limbo_ai/editor/prefer_online_documentation` was also not
available.

Changes:
- Updated EDITOR_DEF macro to handle both module and GDExtension cases
- Remove special case for `limbo_ai/editor/layout` in
  LimboAiEditorPlugin from earlier fix.
2024-09-03 16:37:54 +02:00
Serhii Snitsaruk d972b2e7ff
Merge pull request #204 from monxa/fix-editor-setting-gdextension
Fix editor setting initialization for GDExtensions
2024-09-03 02:23:28 +02:00
Alexander Montag a5517313d2 Fix editor setting initialization for GDExtensions
This commit addresses an issue where editor settings were not properly
initialized when using GDExtensions. The problem manifested as an error
message: "Condition '!props.has(pinfo.name)' is true" when trying to
access the "limbo_ai/editor/layout" setting.

Changes:
- Replace Dictionary with PropertyInfo for adding property information
- Add a safeguard to ensure the setting is explicitly set if not present
2024-09-02 10:27:22 +02:00
Serhii Snitsaruk f694980c6d
Merge pull request #202 from limbonaut/fix-custom-scene-root
Fix custom scene root is not used in BTPlayer and BTState
2024-08-31 20:00:47 +02:00
Serhii Snitsaruk b981d430f1
Fix custom scene root is not used in BTPlayer and BTState 2024-08-31 19:37:44 +02:00
Serhii Snitsaruk c0bc484f0c
README: Link to stable documentation instead of latest 2024-08-25 15:24:13 +02:00
Serhii Snitsaruk af68b1eebc
Update README.md 2024-08-22 17:28:02 +02:00
Serhii Snitsaruk f83cf659e8
GHA: Fix error building .NET assemblies for Windows 2024-08-22 14:23:20 +02:00
Serhii Snitsaruk bd0dcb3184
GHA: Add action to build .NET assemblies 2024-08-22 13:07:16 +02:00
Serhii Snitsaruk 338c9c8ccb
Bump version to 1.2.0 2024-08-22 00:50:16 +02:00
Serhii Snitsaruk a92fb9da8e
Merge pull request #201 from limbonaut/fix-undo-redo
Fix editor undo polluting scene history if `BehaviorTree` is not saved to a file
2024-08-21 20:57:51 +02:00
Serhii Snitsaruk 9da16a1e0f
Clean up unused string names 2024-08-21 20:04:35 +02:00
Serhii Snitsaruk 472f360cf9
Switch to contextual behavior tree upon undo action 2024-08-21 17:30:30 +02:00
Serhii Snitsaruk c94ec7613d
Add hack to associate undo-redo actions with global history 2024-08-21 16:40:02 +02:00
Serhii Snitsaruk 9ae61e0556
Merge pull request #200 from limbonaut/dotnet-templates
GHA: Build additional .NET templates - Android & iOS
2024-08-21 01:39:03 +02:00
Serhii Snitsaruk 9c8d782fb2
GHA: Build Android .NET templates 2024-08-20 22:13:07 +02:00
Serhii Snitsaruk d709389c87
GHA: Build iOS .NET templates 2024-08-20 17:34:10 +02:00
Serhii Snitsaruk f550ddd23f
Better error message when failed to read editor setting 2024-08-18 12:41:16 +02:00
Serhii Snitsaruk f232069dc4
Merge pull request #199 from limbonaut/gha-fix-dotnet-template-version
GHA: .NET build workflow fixes
2024-08-17 14:21:53 +02:00
Serhii Snitsaruk 6fabad213e
GHA: Fix nuget versions in linux and macos builds 2024-08-16 23:27:58 +02:00
Serhii Snitsaruk cc3d650d23
Fix .NET incorrect template version in version.txt 2024-08-16 20:20:22 +02:00
Serhii Snitsaruk 3a4caeb298
Merge pull request #198 from limbonaut/fix-btstate-overwriting-bb-vars
Don't overwrite exisiting blackboard variables in `BTState` upon initialization
2024-08-16 11:32:00 +02:00
Serhii Snitsaruk ee404c828a
Doc: Update using-blackboard.rst 2024-08-16 10:53:59 +02:00
Serhii Snitsaruk 43035839b1
Don't warn of mismatch between Object & NodePath 2024-08-16 00:44:37 +02:00
Serhii Snitsaruk cfacd57f15
Warn about type mismatch when populating blackboard 2024-08-15 23:41:39 +02:00
Serhii Snitsaruk 000f9c15d8
Fix BTState overwriting blackboard variables on init 2024-08-15 23:41:36 +02:00
Serhii Snitsaruk d7438b8a8d
Bump version to 1.2-rc 2024-08-15 16:30:42 +02:00
Serhii Snitsaruk b59db1eee8
Merge pull request #197 from limbonaut/gha-nuget-version
GHA: Preserve nuget version for C# builds
2024-08-15 16:12:53 +02:00
Serhii Snitsaruk 26cf0bb6b4
GHA: Preserve nuget version for C# builds 2024-08-15 16:11:00 +02:00
Serhii Snitsaruk 635ada23dd
Merge pull request #195 from limbonaut/fix-mapping-bug
BlackboardPlan: Fix mapping failing for NodePath variables with prefetch enabled
2024-08-14 21:15:33 +02:00
Serhii Snitsaruk e12beee51e
Fix mapping failing for NodePath variables with prefetch enabled 2024-08-14 20:34:56 +02:00
Serhii Snitsaruk 1f6cc8e55c
GHA: Change test build configuration 2024-08-11 12:56:45 +02:00
Serhii Snitsaruk f8ab80defa
Merge pull request #193 from limbonaut/fix-monitor-performance
Fix `monitor_performance` screwing C# exports
2024-08-11 12:43:28 +02:00
Serhii Snitsaruk 314fcfd741
Fix monitor_performance screwing C# exports 2024-08-11 12:37:37 +02:00
Serhii Snitsaruk 6ada9cef2f
Merge pull request #191 from ydeltastar/fix-tab-update
Fix renaming `BehaviorTree` files doesn't update tab names
2024-08-11 11:26:48 +02:00
yds 410efbe0d3 Fix tab names doesn't update when filesystem changes 2024-08-10 11:29:22 -03:00
Serhii Snitsaruk 85d5af180b
Clarify add_event_handler in docs 2024-08-10 15:01:43 +02:00
Serhii Snitsaruk b4eec2c364
Fix event handler signature example in docs 2024-08-10 14:58:20 +02:00
Serhii Snitsaruk 02af29f2fa
Merge pull request #190 from limbonaut/dev-setup
Improved dev setup for GDExtension
2024-08-10 11:06:43 +02:00
Serhii Snitsaruk 3a40de482f
Fix icon *.import files on scons build
Enables editor scaling and color conversion in LimboAI icon imports.
This won't work until icons are actually imported in the godot editor, but that's okay - it's a convenience feature.
2024-08-10 10:32:35 +02:00
Serhii Snitsaruk 1e1fb5adaf
Clone godot-cpp if not found during scons build 2024-08-09 14:21:40 +02:00
Serhii Snitsaruk 80e3ff705d
Remove setup_gdextension.sh & update README 2024-08-09 13:13:26 +02:00
Serhii Snitsaruk 10b90b70fe
GHA: Don't use setup_gdextension.sh (no longer needed) 2024-08-08 22:55:51 +02:00
Serhii Snitsaruk 7708a11840
Deploy icons on scons build (optionally) 2024-08-08 22:00:16 +02:00
Serhii Snitsaruk 98accb1aa8
Automatically deploy limboai.gdextension on build 2024-08-08 14:41:25 +02:00
Serhii Snitsaruk bf33917cfd
Add help and verification for --project option in SConstruct 2024-08-08 13:27:36 +02:00
Serhii Snitsaruk 304bd86220
Write icon entries to manifest only if changed 2024-08-07 17:47:50 +02:00
Serhii Snitsaruk 629062ea26
Update icon entries during scons build 2024-08-07 17:29:08 +02:00
Serhii Snitsaruk 2528741333
Rename update_icons.py to update_icon_entries.py 2024-08-07 17:11:51 +02:00
Serhii Snitsaruk d5becadd59
Add script to fix icon imports in the demo project 2024-08-07 17:04:49 +02:00
Serhii Snitsaruk 7b0d0aa779
GHA: Update GDExtension workflow for new structure 2024-08-07 15:26:40 +02:00
Serhii Snitsaruk 650e381659
update setup_gdextension.sh to work with new GDExtension project structure 2024-08-07 15:15:59 +02:00
Serhii Snitsaruk 6134d5130c
update SConstruct to be used from repo root and add --project option 2024-08-07 15:01:50 +02:00
Serhii Snitsaruk 32d74427e5
chore: move SConstruct to repo root 2024-08-07 14:52:05 +02:00
Serhii Snitsaruk f14a19b947
Merge pull request #189 from ydeltastar/filter-fix
Make player filter in the debugger case-insensitive
2024-08-07 10:11:19 +02:00
yds 1b04a8589f Make player filter in the debugger case-insensitive 2024-08-06 16:34:06 -03:00
Serhii Snitsaruk abb2af7d27
Merge pull request #188 from limbonaut/fix-csharp-export-errors
Fix C# exports print errors due to missing ClassDB binding
2024-08-06 19:57:07 +02:00
Serhii Snitsaruk 84becbe914
Fix C# exports print errors due to missing ClassDB binding 2024-08-06 18:17:55 +02:00
Serhii Snitsaruk 549a595b42
Doc: Fix codeblock broken sphinx 2024-08-05 17:27:43 +02:00
Serhii Snitsaruk a56272a248
Doc: Clarify `LimboState.add_event_handler()` 2024-08-05 17:09:55 +02:00
Serhii Snitsaruk 63de416066
Merge pull request #186 from limbonaut/double-click-to-edit-script
Edit task script on double-click (open help for core task)
2024-08-05 16:54:40 +02:00
Serhii Snitsaruk c19fd54927
Edit task script on double-click (open help for core task) 2024-08-05 16:34:54 +02:00
Serhii Snitsaruk f8c6e83688
Merge pull request #185 from limbonaut/open-builtin-doc
Editor setting to prefer online docs, and open builtin docs by default
2024-08-05 16:29:12 +02:00
Serhii Snitsaruk 5a4893fc53
Editor setting to prefer online docs, and open builtin docs by default 2024-08-05 15:46:02 +02:00
Serhii Snitsaruk 14d8df0858
Merge pull request #184 from limbonaut/custom-scene-root
Allow supplying custom scene root for behavior tree instantiation
2024-08-05 15:18:21 +02:00
Serhii Snitsaruk 868baa470a
Fix documentation errors 2024-08-05 13:34:13 +02:00
Serhii Snitsaruk 319c5787be
Add BTState::set_scene_root_hint() 2024-08-05 13:21:57 +02:00
Serhii Snitsaruk 1e9b321283
Allow setting custom scene root for behavior trees
- Adds new argument to `BehaviorTree.instantiate()`
- Adds `BTPlayer.set_scene_root_hint()` method
2024-08-05 13:03:50 +02:00
Serhii Snitsaruk 8b2770116d
Merge pull request #183 from limbonaut/btplayer-allow-changing-instance
BTPlayer: Allow switching BT instance at runtime
2024-08-04 13:16:48 +02:00
Serhii Snitsaruk 40863313dd
Check if blackboard is null in `BehaviorTree.instantiate()` 2024-08-04 12:41:25 +02:00
Serhii Snitsaruk ee12a56e96
BTPlayer: Allow changing BT instance at runtime 2024-08-04 12:36:44 +02:00
Serhii Snitsaruk 0f82fa3d64
Merge pull request #182 from limbonaut/btstate-monitor-performance
Allow monitoring BT performance in `BTState`
2024-08-04 11:39:02 +02:00
Serhii Snitsaruk df11afaf44
Allow monitoring BT performance in BTState 2024-08-04 10:37:41 +02:00
Serhii Snitsaruk d2ba904243
Merge pull request #181 from limbonaut/bt-instance
Implement `BTInstance` - runtime instance of `BehaviorTree`
2024-08-04 10:15:08 +02:00
Serhii Snitsaruk 63ef3e0555
BTPlayer: Fix `updated` signal and deprecate `behavior_tree_finished` signal 2024-08-03 16:11:47 +02:00
Serhii Snitsaruk 869b6465b9
Unregister BT instance with debugger if BTPlayer is removed from tree 2024-08-03 14:57:57 +02:00
Serhii Snitsaruk 91edd1c0b5
Documentation fixes 2024-08-03 14:39:27 +02:00
Serhii Snitsaruk 6b4c97e545
Fix BehaviorTree.instantiate() method binding 2024-08-03 14:29:24 +02:00
Serhii Snitsaruk 5f5b62a4ea
Fix BTState setup 2024-08-03 14:17:26 +02:00
Serhii Snitsaruk 68a9492f3d
Fix uninitialized integers 2024-08-03 13:48:15 +02:00
Serhii Snitsaruk 9abfe4ce95
Update class docs 2024-08-03 13:14:31 +02:00
Serhii Snitsaruk 6c794d6a7e
Refactor BTInstance.update() 2024-08-03 11:56:32 +02:00
Serhii Snitsaruk 47ad95b265
Fix demo API calls 2024-08-03 11:40:56 +02:00
Serhii Snitsaruk c4c9b5fe09
Utilize BTInstance in BTState 2024-08-03 11:39:23 +02:00
Serhii Snitsaruk fc26f51ff2
Implement BTInstance - runtime instance of BehaviorTree 2024-08-03 11:07:06 +02:00
Serhii Snitsaruk a2a62f636b
Merge pull request #180 from limbonaut/fix-changed-already-connected
Fix error if `changed` signal is already connected in several tasks
2024-08-02 14:43:21 +02:00
Serhii Snitsaruk ce1867be7a
Fix error if `changed` signal is already connected to a BBParam in a bunch of tasks 2024-08-02 10:07:42 +02:00
Serhii Snitsaruk 09185211ff
Merge pull request #177 from limbonaut/hide-update-mode
Hide `update_mode` property for non-root HSMs
2024-07-31 15:26:45 +02:00
Serhii Snitsaruk 9e79183579
Update demo import 2024-07-31 14:50:56 +02:00
Serhii Snitsaruk bed04dbf87
Hide update_mode for non-root HSMs 2024-07-31 14:50:04 +02:00
Serhii Snitsaruk 64df43c7c9
Merge pull request #176 from limbonaut/hsm-input-fix
LimboHSM: Fix process_input is not enabled in active substate
2024-07-31 13:40:50 +02:00
Serhii Snitsaruk d7daa027ee
Merge pull request #174 from limbonaut/gha-arm-builds
GHA: Add Linux & Windows ARM64 builds
2024-07-31 13:28:55 +02:00
Serhii Snitsaruk abe9a26460
GHA: Add Linux ARM32 template builds 2024-07-31 12:45:12 +02:00
Serhii Snitsaruk 2c58cfc3cb
GHA: Don't strip binaries, done at build time 2024-07-31 12:45:02 +02:00
Serhii Snitsaruk a1d6276097
Fix process_input is not enabled in active substate 2024-07-31 12:15:15 +02:00
Serhii Snitsaruk afc2b63f06
GHA: Disable Editor .NET ARM64 2024-07-31 10:43:56 +02:00
Serhii Snitsaruk af27aca021
GHA: Fix strip failing in Linux ARM64 builds 2024-07-30 16:19:02 +02:00
Serhii Snitsaruk dad5082e7e
GHA: Add Linux ARM toolchain 2024-07-30 15:27:58 +02:00
Serhii Snitsaruk 6aa4e63929
Merge pull request #173 from limbonaut/gha-fix-ios-builds
GHA: Fix iOS builds
2024-07-30 15:24:04 +02:00
Serhii Snitsaruk 8568572092
GHA: Add Windows ARM64 builds 2024-07-30 14:20:46 +02:00
Serhii Snitsaruk 3cce7aa0a6
GHA: Add arm64 Linux builds 2024-07-30 14:16:01 +02:00
Serhii Snitsaruk f1dba8f061
GHA: Disable treating warnings as errors for iOS builds 2024-07-30 13:49:59 +02:00
Serhii Snitsaruk 17eb029497
Merge pull request #172 from limbonaut/fix-btplayer-restart-crash
Fix BTPlayer.restart() crash
2024-07-30 13:46:51 +02:00
Serhii Snitsaruk 456687c857
Fix BTPlayer.restart() crash 2024-07-30 12:42:22 +02:00
Serhii Snitsaruk 186ee3c6a7
Update README 2024-07-30 12:02:02 +02:00
180 changed files with 3520 additions and 1351 deletions

View File

@ -0,0 +1,30 @@
name: Build .NET assemblies
inputs:
platform:
required: true
type: choice
options:
- linuxbsd
- windows
- macos
runs:
using: "composite"
steps:
- name: Override GODOT_VERSION_STATUS for NuGet packages
shell: bash
run: |
GODOT_VERSION_STATUS=$(echo "${GODOT_VERSION_STATUS}" | sed "s|+|-|").gha
echo "GODOT_VERSION_STATUS=${GODOT_VERSION_STATUS}" >> "$GITHUB_ENV"
echo "GODOT_VERSION_STATUS: ${GODOT_VERSION_STATUS}"
- name: Generate C# glue
shell: bash
run: |
./bin/${BIN} --headless --generate-mono-glue ./modules/mono/glue || true
- name: Build .NET assemblies
shell: bash
run: |
python ./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=${{ inputs.platform }}

View File

@ -15,7 +15,7 @@ runs:
echo "GDEXTENSION_VERSION=${GDEXTENSION_VERSION}" >> "$GITHUB_ENV" echo "GDEXTENSION_VERSION=${GDEXTENSION_VERSION}" >> "$GITHUB_ENV"
cd ../limboai cd ..
echo "LIMBOAI_VERSION=$( (git describe --tags --exact-match HEAD || git rev-parse --short HEAD) | sed 's/\(.*\)-\(.*\)/\1.\2/g' )" >> "$GITHUB_ENV" echo "LIMBOAI_VERSION=$( (git describe --tags --exact-match HEAD || git rev-parse --short HEAD) | sed 's/\(.*\)-\(.*\)/\1.\2/g' )" >> "$GITHUB_ENV"
- name: Set NAME_PREFIX - name: Set NAME_PREFIX

View File

@ -15,6 +15,11 @@ runs:
TOOLCHAIN_64_SHA=16c8302fcb676c1f0fb9df73d6cff250ba1f4286 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_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 TOOLCHAIN_32_SHA=6171652abc54ef219e5187bc53660ee4e2f796f4
TOOLCHAIN_ARM64_URL=https://github.com/godotengine/buildroot/releases/download/godot-2023.08.x-3/aarch64-godot-linux-gnu_sdk-buildroot.tar.bz2
TOOLCHAIN_ARM64_SHA=73bed3d26b92c8b9a93c0ceb6bcce8fe567d1764
TOOLCHAIN_ARM32_URL=https://github.com/godotengine/buildroot/releases/download/godot-2023.08.x-3/arm-godot-linux-gnueabihf_sdk-buildroot.tar.bz2
TOOLCHAIN_ARM32_SHA=aa5853fd73faec3837c6127649471275d7e61cb2
# ! Export variables: # ! Export variables:
if [[ "${{ inputs.arch }}" == "x86_64" ]]; then if [[ "${{ inputs.arch }}" == "x86_64" ]]; then
echo "TOOLCHAIN_URL=${TOOLCHAIN_64_URL}" >> "$GITHUB_ENV" echo "TOOLCHAIN_URL=${TOOLCHAIN_64_URL}" >> "$GITHUB_ENV"
@ -22,6 +27,12 @@ runs:
elif [[ "${{ inputs.arch }}" == "x86_32" ]]; then elif [[ "${{ inputs.arch }}" == "x86_32" ]]; then
echo "TOOLCHAIN_URL=${TOOLCHAIN_32_URL}" >> "$GITHUB_ENV" echo "TOOLCHAIN_URL=${TOOLCHAIN_32_URL}" >> "$GITHUB_ENV"
echo "TOOLCHAIN_SHA=${TOOLCHAIN_32_SHA}" >> "$GITHUB_ENV" echo "TOOLCHAIN_SHA=${TOOLCHAIN_32_SHA}" >> "$GITHUB_ENV"
elif [[ "${{ inputs.arch }}" == "arm64" ]]; then
echo "TOOLCHAIN_URL=${TOOLCHAIN_ARM64_URL}" >> "$GITHUB_ENV"
echo "TOOLCHAIN_SHA=${TOOLCHAIN_ARM64_SHA}" >> "$GITHUB_ENV"
elif [[ "${{ inputs.arch }}" == "arm32" ]]; then
echo "TOOLCHAIN_URL=${TOOLCHAIN_ARM32_URL}" >> "$GITHUB_ENV"
echo "TOOLCHAIN_SHA=${TOOLCHAIN_ARM32_SHA}" >> "$GITHUB_ENV"
fi fi
- name: Cache buildroot - name: Cache buildroot

View File

@ -5,7 +5,7 @@ on:
godot-ref: godot-ref:
description: A tag, branch or commit hash in the Godot repository. description: A tag, branch or commit hash in the Godot repository.
type: string type: string
default: 4.2 default: 4.3
limboai-ref: limboai-ref:
description: A tag, branch or commit hash in the LimboAI repository. description: A tag, branch or commit hash in the LimboAI repository.
type: string type: string
@ -13,7 +13,7 @@ on:
godot-cpp-ref: godot-cpp-ref:
description: A tag, branch or commit hash in the godot-cpp repository. description: A tag, branch or commit hash in the godot-cpp repository.
type: string type: string
default: 4.2 default: godot-4.3-stable
jobs: jobs:
cache-sha: cache-sha:

View File

@ -37,40 +37,104 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
# * Standard arm64
- name: Template (arm64, debug) - name: Template (arm64, debug)
arch: arm64 arch: arm64
target: template_debug target: template_debug
dotnet: false
- name: Template (arm64, release) - name: Template (arm64, release)
arch: arm64 arch: arm64
target: template_release target: template_release
dotnet: false
# * Standard arm32
- name: Template (arm32, debug) - name: Template (arm32, debug)
arch: arm32 arch: arm32
target: template_debug target: template_debug
dotnet: false
- name: Template (arm32, release) - name: Template (arm32, release)
arch: arm32 arch: arm32
target: template_release target: template_release
dotnet: false
# * Standard x86_64
- name: Template (x86_64, debug) - name: Template (x86_64, debug)
arch: x86_64 arch: x86_64
target: template_debug target: template_debug
dotnet: false
- name: Template (x86_64, release) - name: Template (x86_64, release)
arch: x86_64 arch: x86_64
target: template_release target: template_release
dotnet: false
# * Standard x86_32
- name: Template (x86_32, debug) - name: Template (x86_32, debug)
arch: x86_32 arch: x86_32
target: template_debug target: template_debug
dotnet: false
- name: Template (x86_32, release) - name: Template (x86_32, release)
arch: x86_32 arch: x86_32
target: template_release target: template_release
dotnet: false
# * .NET arm64
- name: Template .NET (arm64, debug)
arch: arm64
target: template_debug
dotnet: true
- name: Template .NET (arm64, release)
arch: arm64
target: template_release
dotnet: true
# * .NET arm32
- name: Template .NET (arm32, debug)
arch: arm32
target: template_debug
dotnet: true
- name: Template .NET (arm32, release)
arch: arm32
target: template_release
dotnet: true
# * .NET x86_64
- name: Template .NET (x86_64, debug)
arch: x86_64
target: template_debug
dotnet: true
- name: Template .NET (x86_64, release)
arch: x86_64
target: template_release
dotnet: true
# * .NET x86_32
- name: Template .NET (x86_32, debug)
arch: x86_32
target: template_debug
dotnet: true
- name: Template .NET (x86_32, release)
arch: x86_32
target: template_release
dotnet: true
env: env:
BIN: godot.linuxbsd.${{matrix.target}}.${{matrix.arch}} #${{ matrix.build-mono == true && '.mono' || '' }} BIN: godot.linuxbsd.${{matrix.target}}.${{matrix.arch}}${{ matrix.dotnet == true && '.mono' || '' }}
steps: steps:
- name: Clone Godot - name: Clone Godot
@ -115,19 +179,28 @@ jobs:
env: env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/ SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: | run: |
scons platform=android target=${{matrix.target}} arch=${{matrix.arch}} ${{env.SCONSFLAGS}} scons platform=android target=${{matrix.target}} arch=${{matrix.arch}} module_mono_enabled=${{matrix.dotnet}} ${{env.SCONSFLAGS}}
ls platform/android/java/lib/libs/* ls platform/android/java/lib/libs/*
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: tmp-android-templates-${{strategy.job-index}} name: tmp-android${{matrix.dotnet == true && '-dotnet' || ''}}-templates-${{strategy.job-index}}
path: platform/android/java/lib/libs/* path: platform/android/java/lib/libs/*
make-android-package: make-android-package:
runs-on: "ubuntu-20.04" runs-on: "ubuntu-20.04"
name: Make Android package
needs: android-builds needs: android-builds
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Package Android templates
dotnet: false
- name: Package Android .NET templates
dotnet: true
steps: steps:
- name: Clone Godot - name: Clone Godot
@ -148,7 +221,7 @@ jobs:
- name: Download Android template builds - name: Download Android template builds
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
pattern: tmp-android-templates-* pattern: tmp-android${{matrix.dotnet == true && '-dotnet' || ''}}-templates-*
merge-multiple: true merge-multiple: true
path: platform/android/java/lib/libs/ path: platform/android/java/lib/libs/
@ -180,24 +253,24 @@ jobs:
mkdir -p out/templates/ mkdir -p out/templates/
mv bin/android_* out/templates/ mv bin/android_* out/templates/
echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}" > out/templates/version.txt echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}${{matrix.dotnet == true && '.mono' || ''}}" > out/templates/version.txt
ls -l out/* ls -l out/*
- name: Delete Android template builds - name: Delete Android template builds
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v5
with: with:
name: tmp-android-templates-* name: tmp-android${{matrix.dotnet == true && '-dotnet' || ''}}-templates-*
useGlob: true useGlob: true
failOnError: false failOnError: false
- name: Upload Android libs - name: Upload Android libs
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{env.NAME_PREFIX}}.android-lib name: ${{env.NAME_PREFIX}}${{matrix.dotnet == true && '.dotnet' || ''}}.android-lib
path: bin/godot-lib.* path: bin/godot-lib.*
- name: Upload Android templates - name: Upload Android templates
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{env.NAME_PREFIX}}.export-templates.android name: ${{env.NAME_PREFIX}}${{matrix.dotnet == true && '.dotnet' || ''}}.export-templates.android
path: out/* path: out/*

View File

@ -5,13 +5,17 @@ on:
godot-cpp-ref: godot-cpp-ref:
description: A tag, branch or commit hash in the godot-cpp repository. description: A tag, branch or commit hash in the godot-cpp repository.
type: string type: string
default: master default: godot-4.3-stable
limboai-ref: limboai-ref:
description: A tag, branch or commit hash in the LimboAI repository. description: A tag, branch or commit hash in the LimboAI repository.
type: string type: string
default: master default: master
test-build: test-build:
description: Should we perform only a limited number of test builds? description: Limit the number of test builds
type: boolean
default: false
debug-symbols:
description: Build with debug symbols
type: boolean type: boolean
default: false default: false
@ -20,23 +24,27 @@ on:
godot-cpp-ref: godot-cpp-ref:
description: A tag, branch or commit hash in the godot-cpp repository. description: A tag, branch or commit hash in the godot-cpp repository.
type: string type: string
default: master default: godot-4.3-stable
limboai-ref: limboai-ref:
description: A tag, branch or commit hash in the LimboAI repository. description: A tag, branch or commit hash in the LimboAI repository.
type: string type: string
default: master default: master
test-build: test-build:
description: Should we perform only a limited number of test builds? description: Limit the number of test builds
type: boolean
default: false
debug-symbols:
description: Build with debug symbols
type: boolean type: boolean
default: false default: false
# Global Settings # Global Settings
env: env:
SCONS_CACHE_LIMIT: 4096 SCONS_CACHE_LIMIT: 4096
SCONSFLAGS: dev_build=no debug_symbols=no SCONSFLAGS: use_mingw=yes dev_build=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 GODOT_VERSION: 4.3-stable
jobs: jobs:
gdextension: gdextension:
@ -197,6 +205,12 @@ jobs:
BIN: liblimboai.${{matrix.opts.platform}}.${{matrix.opts.target}}.${{matrix.opts.arch}} BIN: liblimboai.${{matrix.opts.platform}}.${{matrix.opts.target}}.${{matrix.opts.arch}}
steps: steps:
- name: Clone LimboAI module
uses: actions/checkout@v4
with:
fetch-tags: true
ref: ${{ inputs.limboai-ref }}
- name: Clone godot-cpp - name: Clone godot-cpp
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@ -205,15 +219,8 @@ jobs:
path: godot-cpp path: godot-cpp
ref: ${{ inputs.godot-cpp-ref }} ref: ${{ inputs.godot-cpp-ref }}
- name: Clone LimboAI module
uses: actions/checkout@v4
with:
path: limboai
fetch-tags: true
ref: ${{ inputs.limboai-ref }}
# Inits GDEXTENSION_VERSION, LIMBOAI_VERSION and NAME_PREFIX environment variables. # Inits GDEXTENSION_VERSION, LIMBOAI_VERSION and NAME_PREFIX environment variables.
- uses: ./limboai/.github/actions/init-version-gdext - uses: ./.github/actions/init-version-gdext
- name: Output NAME_PREFIX - name: Output NAME_PREFIX
id: output-name-prefix id: output-name-prefix
@ -221,7 +228,7 @@ jobs:
- name: Setup Linux toolchain - name: Setup Linux toolchain
if: matrix.opts.platform == 'linux' if: matrix.opts.platform == 'linux'
uses: ./limboai/.github/actions/setup-linux-toolchain uses: ./.github/actions/setup-linux-toolchain
with: with:
arch: ${{matrix.opts.arch}} arch: ${{matrix.opts.arch}}
@ -281,57 +288,35 @@ jobs:
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: ${{github.workspace}}/.scons_cache/ path: ${{github.workspace}}/.scons_cache/
key: ${{env.BIN}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}}-${{env.LIMBOAI_VERSION}} key: ${{env.BIN}}-${{inputs.debug-symbols}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}}-${{env.LIMBOAI_VERSION}}
restore-keys: | restore-keys: |
${{env.BIN}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}}-${{env.LIMBOAI_VERSION}} ${{env.BIN}}-${{inputs.debug-symbols}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}}-${{env.LIMBOAI_VERSION}}
${{env.BIN}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}} ${{env.BIN}}-${{inputs.debug-symbols}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}}
${{env.BIN}}-${{inputs.godot-cpp-ref}} ${{env.BIN}}-${{inputs.debug-symbols}}-${{inputs.godot-cpp-ref}}
- name: Setup project structure for GDExtension
shell: bash
run: |
bash ./limboai/gdextension/setup_gdextension.sh --copy-all
echo "---"
ls -l
echo "---"
ls -l -R ./demo/
- name: Compilation - name: Compilation
shell: bash shell: bash
env: env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/ SCONS_CACHE: ${{github.workspace}}/.scons_cache/
DEBUG_FLAGS: ${{ inputs.debug-symbols && 'debug_symbols=yes symbols_visibility=visible' || 'debug_symbols=no' }}
run: | run: |
PATH=${GITHUB_WORKSPACE}/buildroot/bin:$PATH PATH=${GITHUB_WORKSPACE}/buildroot/bin:$PATH
scons platform=${{matrix.opts.platform}} target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} ${{matrix.opts.scons-flags}} ${{env.SCONSFLAGS}} scons platform=${{matrix.opts.platform}} target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} ${{env.DEBUG_FLAGS}} ${{matrix.opts.scons-flags}} ${{env.SCONSFLAGS}}
- name: Prepare artifact - name: Prepare artifact
shell: bash shell: bash
run: | run: |
ls -R demo/addons/limboai/
mkdir out mkdir out
mv demo/addons/ out/ mv demo/addons/ out/
cp limboai/{README,LICENSE,LOGO_LICENSE}.md out/addons/limboai/ cp {README,LICENSE,LOGO_LICENSE}.md out/addons/limboai/
cp -R limboai/demo/demo/ out/demo/ cp -R demo/demo/ out/demo/
cp limboai/demo/LICENSE_ASSETS.md out/demo/ cp demo/LICENSE_ASSETS.md out/demo/
rm -f out/addons/limboai/bin/*.{exp,lib,pdb} rm -f out/addons/limboai/bin/*.{exp,lib,pdb}
echo "${LIMBOAI_VERSION}" > out/addons/limboai/version.txt echo "${LIMBOAI_VERSION}" > out/addons/limboai/version.txt
echo "---" echo "---"
ls -R out/ ls -R out/
- name: Strip lib
if: matrix.opts.platform != 'windows' && matrix.opts.platform != 'web' && (matrix.opts.platform != 'android' || startsWith(matrix.opts.arch, 'x86'))
run: |
ls -l -R out/addons/limboai/bin/
echo "---"
if [ "${{matrix.opts.platform}}" == "macos" ]; then
strip -u out/addons/limboai/bin/liblimboai*/liblimboai*
elif [ "${{matrix.opts.platform}}" == "ios" ]; then
strip -u out/addons/limboai/bin/liblimboai*
else
strip out/addons/limboai/bin/liblimboai*
fi
echo "---"
ls -l -R out/addons/limboai/bin/
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
env: env:

View File

@ -25,7 +25,7 @@ on:
# Global Settings # Global Settings
env: env:
SCONS_CACHE_LIMIT: 4096 SCONS_CACHE_LIMIT: 4096
SCONSFLAGS: production=yes tests=no verbose=yes warnings=extra werror=yes SCONSFLAGS: production=yes tests=no verbose=yes warnings=extra
DOTNET_NOLOGO: true DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true DOTNET_CLI_TELEMETRY_OPTOUT: true
@ -42,21 +42,25 @@ jobs:
target: template_release target: template_release
arch: arm64 arch: arm64
ios_simulator: false ios_simulator: false
dotnet: false
- name: Template (arm64, debug) - name: Template (arm64, debug)
target: template_debug target: template_debug
arch: arm64 arch: arm64
ios_simulator: false ios_simulator: false
dotnet: false
- name: Simulator Lib (x86_64, release) - name: Simulator (x86_64, release)
target: template_release target: template_release
arch: x86_64 arch: x86_64
ios_simulator: true ios_simulator: true
dotnet: false
- name: Simulator Lib (x86_64, debug) - name: Simulator (x86_64, debug)
target: template_debug target: template_debug
arch: x86_64 arch: x86_64
ios_simulator: true ios_simulator: true
dotnet: false
# ! Disabled for now as it doesn't work with cctools-port and current LLVM. # ! Disabled for now as it doesn't work with cctools-port and current LLVM.
# * See https://github.com/godotengine/build-containers/pull/85. # * See https://github.com/godotengine/build-containers/pull/85.
@ -70,8 +74,32 @@ jobs:
# arch: arm64 # arch: arm64
# ios_simulator: true # ios_simulator: true
- name: Template .NET (arm64, release)
target: template_release
arch: arm64
ios_simulator: false
dotnet: true
- name: Template .NET (arm64, debug)
target: template_debug
arch: arm64
ios_simulator: false
dotnet: true
- name: Simulator .NET (x86_64, release)
target: template_release
arch: x86_64
ios_simulator: true
dotnet: true
- name: Simulator .NET (x86_64, debug)
target: template_debug
arch: x86_64
ios_simulator: true
dotnet: true
env: env:
BIN: godot.ios.${{matrix.target}}.${{matrix.arch}} BIN: godot.ios.${{matrix.target}}.${{matrix.arch}}${{ matrix.dotnet == true && '.mono' || '' }}
steps: steps:
- name: Clone Godot - name: Clone Godot
@ -124,19 +152,28 @@ jobs:
env: env:
SCONS_CACHE: ${{github.workspace}}/.scons_cache/ SCONS_CACHE: ${{github.workspace}}/.scons_cache/
run: | run: |
scons platform=ios target=${{matrix.target}} arch=${{matrix.arch}} ios_simulator=${{matrix.ios_simulator}} ${{env.SCONSFLAGS}} scons platform=ios target=${{matrix.target}} arch=${{matrix.arch}} ios_simulator=${{matrix.ios_simulator}} module_mono_enabled=${{matrix.dotnet}} ${{env.SCONSFLAGS}}
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: tmp-ios-templates-${{strategy.job-index}} name: tmp-ios${{matrix.dotnet == true && '-dotnet' || ''}}-templates-${{strategy.job-index}}
path: bin/* path: bin/*
package-ios-templates: package-ios-templates:
runs-on: "macos-latest" runs-on: "macos-latest"
name: Package iOS templates name: ${{ matrix.name }}
needs: ios-builds needs: ios-builds
strategy:
fail-fast: false
matrix:
include:
- name: Package iOS templates
dotnet: false
- name: Package iOS .NET templates
dotnet: true
steps: steps:
- name: Clone Godot - name: Clone Godot
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -160,7 +197,7 @@ jobs:
- name: Download templates artifact - name: Download templates artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
pattern: tmp-ios-templates-* pattern: tmp-ios${{matrix.dotnet == true && '-dotnet' || ''}}-templates-*
merge-multiple: true merge-multiple: true
path: bin/ path: bin/
@ -170,9 +207,6 @@ jobs:
cp -r misc/dist/ios_xcode bin/ cp -r misc/dist/ios_xcode bin/
cd bin/ cd bin/
# --- Note: Doesn't look like libs need stripping ---
# strip *.a
mv libgodot.ios.template_debug.arm64.a ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/libgodot.a mv libgodot.ios.template_debug.arm64.a ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/libgodot.a
# ! lipo -create libgodot.ios.template_debug.arm64.simulator.a libgodot.ios.template_debug.x86_64.simulator.a -output ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/libgodot.a # ! lipo -create libgodot.ios.template_debug.arm64.simulator.a libgodot.ios.template_debug.x86_64.simulator.a -output ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/libgodot.a
mv libgodot.ios.template_debug.x86_64.simulator.a ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/libgodot.a mv libgodot.ios.template_debug.x86_64.simulator.a ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/libgodot.a
@ -188,19 +222,19 @@ jobs:
cd ios_xcode cd ios_xcode
zip -q -9 -r ${{github.workspace}}/out/templates/ios.zip * zip -q -9 -r ${{github.workspace}}/out/templates/ios.zip *
echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}" > ${{github.workspace}}/out/templates/version.txt echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}${{matrix.dotnet == true && '.mono' || ''}}" > ${{github.workspace}}/out/templates/version.txt
ls -l ${{github.workspace}}/out/* ls -l ${{github.workspace}}/out/*
- name: Upload template bundle - name: Upload template bundle
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{env.NAME_PREFIX}}.export-templates.ios name: ${{env.NAME_PREFIX}}${{matrix.dotnet == true && '.dotnet' || ''}}.export-templates.ios
path: out/* path: out/*
- name: Delete templates artifact - name: Delete templates artifact
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v5
with: with:
name: tmp-ios-templates-* name: tmp-ios${{matrix.dotnet == true && '-dotnet' || ''}}-templates-*
useGlob: true useGlob: true
failOnError: false failOnError: false

View File

@ -45,6 +45,8 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
opts: opts:
# * Standard x86_64
- name: Editor (x86_64, release) - name: Editor (x86_64, release)
target: editor target: editor
arch: x86_64 arch: x86_64
@ -63,6 +65,8 @@ jobs:
dotnet: false dotnet: false
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * Standard x86_32
# - name: Editor (x86_32, release) # - name: Editor (x86_32, release)
# target: editor # target: editor
# arch: x86_32 # arch: x86_32
@ -81,11 +85,47 @@ jobs:
dotnet: false dotnet: false
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * Standard arm64
- name: Editor (arm64, release)
target: editor
arch: arm64
dotnet: false
should-build: ${{ !inputs.test-build }}
- name: Template (arm64, release)
target: template_release
arch: arm64
dotnet: false
should-build: ${{ !inputs.test-build }}
- name: Template (arm64, debug)
target: template_debug
arch: arm64
dotnet: false
should-build: ${{ !inputs.test-build }}
# * Standard arm32
- name: Template (arm32, release)
target: template_release
arch: arm32
dotnet: false
should-build: ${{ !inputs.test-build }}
- name: Template (arm32, debug)
target: template_debug
arch: arm32
dotnet: false
should-build: ${{ !inputs.test-build }}
# * .NET x86_64
- name: Editor .NET (x86_64, release) - name: Editor .NET (x86_64, release)
target: editor target: editor
arch: x86_64 arch: x86_64
dotnet: true dotnet: true
should-build: ${{ !inputs.test-build }} should-build: true
- name: Template .NET (x86_64, release) - name: Template .NET (x86_64, release)
target: template_release target: template_release
@ -99,6 +139,8 @@ jobs:
dotnet: true dotnet: true
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * .NET x86_32
# - name: Editor .NET (x86_32, release) # - name: Editor .NET (x86_32, release)
# target: editor # target: editor
# arch: x86_32 # arch: x86_32
@ -117,6 +159,42 @@ jobs:
dotnet: true dotnet: true
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * .NET arm64
# ! FIXME: Needs a separate job for .NET glue generation since we can't execute arm64 binaries on x86_64.
# ! Alternatively, solution generation can be done as post-process job, taking the glue from x86_64, after all builds complete.
# - name: Editor .NET (arm64, release)
# target: editor
# arch: arm64
# dotnet: true
# should-build: ${{ !inputs.test-build }}
- name: Template .NET (arm64, release)
target: template_release
arch: arm64
dotnet: true
should-build: ${{ !inputs.test-build }}
- name: Template .NET (arm64, debug)
target: template_debug
arch: arm64
dotnet: true
should-build: ${{ !inputs.test-build }}
# * .NET arm32
- name: Template .NET (arm32, release)
target: template_release
arch: arm32
dotnet: true
should-build: ${{ !inputs.test-build }}
- name: Template .NET (arm32, debug)
target: template_debug
arch: arm32
dotnet: true
should-build: ${{ !inputs.test-build }}
exclude: exclude:
- { opts: { should-build: false } } - { opts: { should-build: false } }
@ -165,25 +243,16 @@ jobs:
PATH=${GITHUB_WORKSPACE}/buildroot/bin:$PATH PATH=${GITHUB_WORKSPACE}/buildroot/bin:$PATH
scons platform=linuxbsd target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} module_mono_enabled=${{matrix.opts.dotnet}} ${{env.SCONSFLAGS}} scons platform=linuxbsd target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} module_mono_enabled=${{matrix.opts.dotnet}} ${{env.SCONSFLAGS}}
- name: Generate C# glue - name: Build .NET assemblies
if: matrix.opts.dotnet && matrix.opts.target == 'editor' if: matrix.opts.dotnet && matrix.opts.target == 'editor'
env: uses: ./modules/limboai/.github/actions/build-dotnet-assemblies
GODOT_VERSION_STATUS: limboai with:
run: | platform: linuxbsd
./bin/$BIN --headless --generate-mono-glue ./modules/mono/glue || true
- name: Build .NET solutions
if: matrix.opts.dotnet && matrix.opts.target == 'editor'
env:
GODOT_VERSION_STATUS: limboai
run: |
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd
- name: Prepare artifact - name: Prepare artifact
env: env:
OUTDIR: ${{ startsWith(matrix.opts.target, 'template') && 'out/templates' || 'out/' }} OUTDIR: ${{ startsWith(matrix.opts.target, 'template') && 'out/templates' || 'out/' }}
run: | run: |
strip ./bin/godot.*
chmod +x ./bin/godot.* chmod +x ./bin/godot.*
mkdir -p ${{env.OUTDIR}} mkdir -p ${{env.OUTDIR}}
mv bin/* ${{env.OUTDIR}} mv bin/* ${{env.OUTDIR}}
@ -208,7 +277,7 @@ jobs:
BUILD_TYPE: ${{ endsWith(matrix.opts.target, 'release') && 'release' || 'debug' }} BUILD_TYPE: ${{ endsWith(matrix.opts.target, 'release') && 'release' || 'debug' }}
run: | run: |
mv out/templates/${BIN} out/templates/linux_${BUILD_TYPE}.${{matrix.opts.arch}} mv out/templates/${BIN} out/templates/linux_${BUILD_TYPE}.${{matrix.opts.arch}}
echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}" > out/templates/version.txt echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}${{matrix.opts.dotnet == true && '.mono' || ''}}" > out/templates/version.txt
ls -R out/ ls -R out/
- name: Upload artifact - name: Upload artifact

View File

@ -165,7 +165,14 @@ jobs:
- name: Set up Vulkan SDK - name: Set up Vulkan SDK
run: | run: |
sh misc/scripts/install_vulkan_sdk_macos.sh # ! Note: Vulkan SDK changed packaging, so we need to inline these steps for the time being.
#sh misc/scripts/install_vulkan_sdk_macos.sh
curl -L "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.zip" -o /tmp/vulkan-sdk.zip
unzip /tmp/vulkan-sdk.zip -d /tmp
/tmp/InstallVulkan.app/Contents/MacOS/InstallVulkan --accept-licenses --default-answer --confirm-command install
rm -Rf /tmp/InstallVulkan.app
rm -f /tmp/vulkan-sdk.zip
- name: Set up scons cache - name: Set up scons cache
uses: actions/cache@v4 uses: actions/cache@v4
@ -183,23 +190,14 @@ jobs:
run: | run: |
scons -j2 platform=macos target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} module_mono_enabled=${{matrix.opts.dotnet}} ${{env.SCONSFLAGS}} scons -j2 platform=macos target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} module_mono_enabled=${{matrix.opts.dotnet}} ${{env.SCONSFLAGS}}
- name: Generate C# glue - name: Build .NET assemblies
if: matrix.opts.dotnet && matrix.opts.target == 'editor' && matrix.opts.arch == 'x86_64' if: matrix.opts.dotnet && matrix.opts.target == 'editor'
env: uses: ./modules/limboai/.github/actions/build-dotnet-assemblies
GODOT_VERSION_STATUS: limboai with:
run: | platform: macos
./bin/$BIN --headless --generate-mono-glue ./modules/mono/glue || true
- name: Build .NET solutions
if: matrix.opts.dotnet && matrix.opts.target == 'editor' && matrix.opts.arch == 'x86_64'
env:
GODOT_VERSION_STATUS: limboai
run: |
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=macos
- name: Prepare artifact - name: Prepare artifact
run: | run: |
strip bin/godot.*
chmod +x bin/godot.* chmod +x bin/godot.*
- name: Upload artifact - name: Upload artifact
@ -257,9 +255,6 @@ jobs:
run: | run: |
ls bin/ ls bin/
lipo -create bin/godot.macos.editor.x86_64* bin/godot.macos.editor.arm64* -output bin/godot.macos.editor.universal lipo -create bin/godot.macos.editor.x86_64* bin/godot.macos.editor.arm64* -output bin/godot.macos.editor.universal
du -sh bin/
strip bin/godot.macos.editor.universal
du -sh bin/
mkdir -p out/editor/ mkdir -p out/editor/
cp -r misc/dist/macos_tools.app out/editor/${APP_NAME} cp -r misc/dist/macos_tools.app out/editor/${APP_NAME}
mkdir -p out/editor/${APP_NAME}/Contents/{MacOS,Resources} mkdir -p out/editor/${APP_NAME}/Contents/{MacOS,Resources}
@ -295,7 +290,6 @@ jobs:
ls bin/ ls bin/
lipo -create bin/godot.macos.template_release.x86_64* bin/godot.macos.template_release.arm64* -output bin/godot.macos.template_release.universal lipo -create bin/godot.macos.template_release.x86_64* bin/godot.macos.template_release.arm64* -output bin/godot.macos.template_release.universal
lipo -create bin/godot.macos.template_debug.x86_64* bin/godot.macos.template_debug.arm64* -output bin/godot.macos.template_debug.universal lipo -create bin/godot.macos.template_debug.x86_64* bin/godot.macos.template_debug.arm64* -output bin/godot.macos.template_debug.universal
strip bin/godot.*.universal
cp -r misc/dist/macos_template.app macos_template.app cp -r misc/dist/macos_template.app macos_template.app
mkdir -p macos_template.app/Contents/MacOS mkdir -p macos_template.app/Contents/MacOS
cp bin/godot.macos.template_debug.universal macos_template.app/Contents/MacOS/godot_macos_debug.universal cp bin/godot.macos.template_debug.universal macos_template.app/Contents/MacOS/godot_macos_debug.universal
@ -304,7 +298,7 @@ jobs:
zip -q -9 -r macos.zip macos_template.app zip -q -9 -r macos.zip macos_template.app
mkdir -p out/templates/ mkdir -p out/templates/
mv macos.zip out/templates/macos.zip mv macos.zip out/templates/macos.zip
echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}" > out/templates/version.txt echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}${{matrix.opts.dotnet == true && '.mono' || ''}}" > out/templates/version.txt
rm -rf bin/* rm -rf bin/*
ls out/templates/ ls out/templates/

View File

@ -26,8 +26,8 @@ concurrency:
# Global Settings. # Global Settings.
env: env:
GODOT_REF: "master" GODOT_REF: "4.3"
GODOT_CPP_REF: "master" GODOT_CPP_REF: "godot-4.3-stable"
jobs: jobs:
unit-tests: unit-tests:
@ -101,6 +101,18 @@ jobs:
run: | run: |
bin/${{ env.BIN }} --test --headless bin/${{ env.BIN }} --test --headless
static-checks:
name: ⚙️ Static checks
runs-on: ubuntu-20.04
steps:
- name: Clone LimboAI module
uses: actions/checkout@v4
- name: Code style checks
uses: pre-commit/action@v3.0.1
with:
extra_args: --all-files
cache-env: cache-env:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:

View File

@ -46,6 +46,8 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
opts: opts:
# * Standard x86_64
- name: Editor (x86_64, release) - name: Editor (x86_64, release)
target: editor target: editor
arch: x86_64 arch: x86_64
@ -64,6 +66,8 @@ jobs:
dotnet: false dotnet: false
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * Standard x86_32
# - name: Editor (x86_32, release) # - name: Editor (x86_32, release)
# target: editor # target: editor
# arch: x86_32 # arch: x86_32
@ -82,11 +86,33 @@ jobs:
dotnet: false dotnet: false
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * Standard arm64
# - name: Editor (arm64, release)
# target: editor
# arch: arm64
# dotnet: false
# should-build: ${{ !inputs.test-build }}
- name: Template (arm64, release)
target: template_release
arch: arm64
dotnet: false
should-build: ${{ !inputs.test-build }}
- name: Template (arm64, debug)
target: template_debug
arch: arm64
dotnet: false
should-build: ${{ !inputs.test-build }}
# * .NET x86_64
- name: Editor .NET (x86_64, release) - name: Editor .NET (x86_64, release)
target: editor target: editor
arch: x86_64 arch: x86_64
dotnet: true dotnet: true
should-build: true should-build: ${{ !inputs.test-build }}
- name: Template .NET (x86_64, release) - name: Template .NET (x86_64, release)
target: template_release target: template_release
@ -100,6 +126,8 @@ jobs:
dotnet: true dotnet: true
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * .NET x86_32
# - name: Editor .NET (x86_32, release) # - name: Editor .NET (x86_32, release)
# target: editor # target: editor
# arch: x86_32 # arch: x86_32
@ -118,6 +146,26 @@ jobs:
dotnet: true dotnet: true
should-build: ${{ !inputs.test-build }} should-build: ${{ !inputs.test-build }}
# * .NET arm64
# - name: Editor (arm64, release)
# target: editor
# arch: arm64
# dotnet: true
# should-build: ${{ !inputs.test-build }}
- name: Template (arm64, release)
target: template_release
arch: arm64
dotnet: true
should-build: ${{ !inputs.test-build }}
- name: Template (arm64, debug)
target: template_debug
arch: arm64
dotnet: true
should-build: ${{ !inputs.test-build }}
exclude: exclude:
- { opts: { should-build: false } } - { opts: { should-build: false } }
@ -172,19 +220,11 @@ jobs:
run: | run: |
scons -j2 platform=windows target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} module_mono_enabled=${{matrix.opts.dotnet}} ${{env.SCONSFLAGS}} scons -j2 platform=windows target=${{matrix.opts.target}} arch=${{matrix.opts.arch}} module_mono_enabled=${{matrix.opts.dotnet}} ${{env.SCONSFLAGS}}
- name: Generate C# glue - name: Build .NET assemblies
if: matrix.opts.dotnet && matrix.opts.target == 'editor' if: matrix.opts.dotnet && matrix.opts.target == 'editor'
env: uses: ./modules/limboai/.github/actions/build-dotnet-assemblies
GODOT_VERSION_STATUS: limboai with:
run: | platform: windows
./bin/${{ env.BIN }} --headless --generate-mono-glue ./modules/mono/glue || true
- name: Build .NET solutions
if: matrix.opts.dotnet && matrix.opts.target == 'editor'
env:
GODOT_VERSION_STATUS: limboai
run: |
python ./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=windows
- name: Prepare artifact - name: Prepare artifact
shell: bash shell: bash
@ -204,7 +244,7 @@ jobs:
run: | run: |
mv out/templates/${BIN}.exe out/templates/windows_${BUILD_TYPE}_${{matrix.opts.arch}}.exe mv out/templates/${BIN}.exe out/templates/windows_${BUILD_TYPE}_${{matrix.opts.arch}}.exe
mv out/templates/${BIN}.console.exe out/templates/windows_${BUILD_TYPE}_${{matrix.opts.arch}}_console.exe mv out/templates/${BIN}.console.exe out/templates/windows_${BUILD_TYPE}_${{matrix.opts.arch}}_console.exe
echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}" > out/templates/version.txt echo "${GODOT_VERSION}.limboai+${LIMBOAI_VERSION}${{matrix.opts.dotnet == true && '.mono' || ''}}" > out/templates/version.txt
ls -R out/ ls -R out/
- name: Upload artifact - name: Upload artifact

4
.gitignore vendored
View File

@ -2,6 +2,7 @@
demo/addons/ demo/addons/
demo/script_templates/ demo/script_templates/
icons/*.import icons/*.import
godot-cpp
# Godot auto generated files # Godot auto generated files
*.gen.* *.gen.*
@ -186,3 +187,6 @@ godot.creator.*
# compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html) # compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
compile_commands.json compile_commands.json
# clang cache
.cache

View File

@ -8,22 +8,23 @@
[![🔎 Unit Tests](https://github.com/limbonaut/limboai/actions/workflows/test_builds.yml/badge.svg)](https://github.com/limbonaut/limboai/actions/workflows/test_builds.yml) [![🔎 Unit Tests](https://github.com/limbonaut/limboai/actions/workflows/test_builds.yml/badge.svg)](https://github.com/limbonaut/limboai/actions/workflows/test_builds.yml)
[![Documentation Status](https://readthedocs.org/projects/limboai/badge/?version=latest)](https://limboai.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/limboai/badge/?version=latest)](https://limboai.readthedocs.io/en/latest/?badge=latest)
[![GitHub License](https://img.shields.io/github/license/limbonaut/limboai)](https://github.com/limbonaut/limboai/blob/master/LICENSE.md) [![GitHub License](https://img.shields.io/github/license/limbonaut/limboai)](https://github.com/limbonaut/limboai/blob/master/LICENSE.md)
[![Discord](https://img.shields.io/discord/1185664967379267774?logo=discord&link=https%3A%2F%2Fdiscord.gg%2FN5MGC95GpP)](https://discord.gg/N5MGC95GpP) [![Discord](https://img.shields.io/discord/1185664967379267774?logo=discord&link=https%3A%2F%2Fdiscord.gg%2FN5MGC95GpP)](https://discord.gg/N5MGC95GpP)
[![Support this project](https://img.shields.io/badge/Support%20this%20project-red?logo=kofi&logoColor=white&link=https%3A%2F%2Fko-fi.com%2Flimbonaut)](https://ko-fi.com/limbonaut)
[![Mastodon Follow](https://img.shields.io/mastodon/follow/109346796150895359?domain=https%3A%2F%2Fmastodon.gamedev.place)](https://mastodon.gamedev.place/@limbo) [![Mastodon Follow](https://img.shields.io/mastodon/follow/109346796150895359?domain=https%3A%2F%2Fmastodon.gamedev.place)](https://mastodon.gamedev.place/@limbo)
>**🛈 Supported Godot Engine:** **4.3** (v1.2.0+) | **4.2** (v1.1.x releases)
**LimboAI** is an open-source C++ plugin for **Godot Engine 4** providing a combination of **LimboAI** is an open-source C++ plugin for **Godot Engine 4** providing a combination of
**Behavior Trees** and **State Machines**, which can be used together to create complex AI behaviors. **Behavior Trees** and **State Machines**, which can be used together to create complex AI behaviors.
It comes with a behavior tree editor, built-in documentation, visual debugger, extensive demo project with a tutorial, and more! It comes with a behavior tree editor, built-in documentation, visual debugger, extensive demo project with a tutorial, and more!
While it is implemented in C++, it fully supports GDScript for [creating your own tasks](https://limboai.readthedocs.io/en/latest/getting-started/custom-tasks.html) and [states](https://limboai.readthedocs.io/en/latest/getting-started/hsm.html). While it is implemented in C++, it fully supports GDScript for [creating your own tasks](https://limboai.readthedocs.io/en/stable/getting-started/custom-tasks.html) and [states](https://limboai.readthedocs.io/en/stable/getting-started/hsm.html).
>**🛈 Supported Godot Engine: 4.2** If you enjoy using LimboAI, please **consider supporting** my efforts with a donation on Ko-fi 😊 Your contribution will help me continue developing and improving it.
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y2TCNH0)
![Textured screenshot](doc/images/behavior-tree-editor-debugger.png) ![Textured screenshot](doc/images/behavior-tree-editor-debugger.png)
Behavior Trees are powerful hierarchical structures used to model and control the behavior of agents in a game (e.g., characters, enemies). They are designed to make it easier to create rich and highly modular behaviors for your games. To learn more about behavior trees, check out [Introduction to Behavior Trees](https://limboai.readthedocs.io/en/latest/getting-started/introduction.html) and our demo project, which includes a tutorial. Behavior Trees are powerful hierarchical structures used to model and control the behavior of agents in a game (e.g., characters, enemies). They are designed to make it easier to create rich and highly modular behaviors for your games. To learn more about behavior trees, check out [Introduction to Behavior Trees](https://limboai.readthedocs.io/en/stable/getting-started/introduction.html) and our demo project, which includes a tutorial.
## Demonstration ## Demonstration
@ -35,8 +36,12 @@ Behavior Trees are powerful hierarchical structures used to model and control th
### Videos ### Videos
> **🛈** YouTube videos produced by various creators
<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=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> <a href="https://www.youtube.com/watch?v=aP0Aacdxmno"><img src="https://img.youtube.com/vi/aP0Aacdxmno/0.jpg" width=410></a>
<a href="https://www.youtube.com/watch?v=vZHzMO90IwQ"><img src="https://img.youtube.com/vi/vZHzMO90IwQ/0.jpg" width=410></a>
<a href="https://www.youtube.com/watch?v=gAk3xl5fBsM"><img src="https://img.youtube.com/vi/gAk3xl5fBsM/0.jpg" width=410></a>
## Features ## Features
@ -45,13 +50,13 @@ Behavior Trees are powerful hierarchical structures used to model and control th
- Execute `BehaviorTree` resources using the `BTPlayer` node. - Execute `BehaviorTree` resources using the `BTPlayer` node.
- Create complex behaviors by combining and nesting tasks in a hierarchy. - Create complex behaviors by combining and nesting tasks in a hierarchy.
- Control execution flow using composite, decorator, and condition tasks. - Control execution flow using composite, decorator, and condition tasks.
- [Create custom tasks](https://limboai.readthedocs.io/en/latest/getting-started/custom-tasks.html) by extending core classes: `BTAction`, `BTCondition`, `BTDecorator`, and `BTComposite`. - [Create custom tasks](https://limboai.readthedocs.io/en/stable/getting-started/custom-tasks.html) by extending core classes: `BTAction`, `BTCondition`, `BTDecorator`, and `BTComposite`.
- Built-in class documentation. - Built-in class documentation.
- Blackboard system: Share data seamlessly between tasks using the `Blackboard`. - Blackboard system: Share data seamlessly between tasks using the `Blackboard`.
- Blackboard plans: Define variables in the BehaviorTree resource and override their values in the BTPlayer node. - Blackboard plans: Define variables in the BehaviorTree resource and override their values in the BTPlayer node.
- Plan editor: Manage variables, their data types and property hints. - Plan editor: Manage variables, their data types and property hints.
- Blackboard scopes: Prevent name conflicts and enable advanced techniques like [sharing data between several agents](https://limboai.readthedocs.io/en/latest/getting-started/using-blackboard.html#sharing-data-between-several-agents). - Blackboard scopes: Prevent name conflicts and enable advanced techniques like [sharing data between several agents](https://limboai.readthedocs.io/en/stable/getting-started/using-blackboard.html#sharing-data-between-several-agents).
- Blackboard parameters: [Export a BB parameter](https://limboai.readthedocs.io/en/latest/getting-started/using-blackboard.html#task-parameters), for which user can provide a value or bind it to a blackboard variable (can be used in custom tasks). - Blackboard parameters: [Export a BB parameter](https://limboai.readthedocs.io/en/stable/getting-started/using-blackboard.html#task-parameters), for which user can provide a value or bind it to a blackboard variable (can be used in custom tasks).
- Inspector support for specifying blackboard variables (custom editor for exported `StringName` properties ending with "_var"). - Inspector support for specifying blackboard variables (custom editor for exported `StringName` properties ending with "_var").
- Use the `BTSubtree` task to execute a tree from a different resource file, promoting organization and reusability. - Use the `BTSubtree` task to execute a tree from a different resource file, promoting organization and reusability.
- Visual Debugger: Inspect the execution of any BT in a running scene to identify and troubleshoot issues. - Visual Debugger: Inspect the execution of any BT in a running scene to identify and troubleshoot issues.
@ -62,24 +67,24 @@ Behavior Trees are powerful hierarchical structures used to model and control th
- Extend the `LimboState` class to implement state logic. - Extend the `LimboState` class to implement state logic.
- `LimboHSM` node serves as a state machine that manages `LimboState` instances and transitions. - `LimboHSM` node serves as a state machine that manages `LimboState` instances and transitions.
- `LimboHSM` is a state itself and can be nested within other `LimboHSM` instances. - `LimboHSM` is a state itself and can be nested within other `LimboHSM` instances.
- [Event-based](https://limboai.readthedocs.io/en/latest/getting-started/hsm.html#events-and-transitions): Transitions are associated with events and are triggered by the state machine when the relevant event is dispatched, allowing for better decoupling of transitions from state logic. - [Event-based](https://limboai.readthedocs.io/en/stable/getting-started/hsm.html#events-and-transitions): Transitions are associated with events and are triggered by the state machine when the relevant event is dispatched, allowing for better decoupling of transitions from state logic.
- Combine state machines with behavior trees using `BTState` for advanced reactive AI. - Combine state machines with behavior trees using `BTState` for advanced reactive AI.
- Delegation Option: Using the vanilla `LimboState`, [delegate the implementation](https://limboai.readthedocs.io/en/latest/getting-started/hsm.html#single-file-state-machine-setup) to your callback functions, making it perfect for rapid prototyping and game jams. - Delegation Option: Using the vanilla `LimboState`, [delegate the implementation](https://limboai.readthedocs.io/en/stable/getting-started/hsm.html#single-file-state-machine-setup) to your callback functions, making it perfect for rapid prototyping and game jams.
- 🛈 Note: State machine setup and initialization require code; there is no GUI editor. - 🛈 Note: State machine setup and initialization require code; there is no GUI editor.
- **Tested:** Behavior tree tasks and HSM are covered by unit tests. - **Tested:** Behavior tree tasks and HSM are covered by unit tests.
- **GDExtension:** LimboAI can be [used as extension](https://limboai.readthedocs.io/en/latest/getting-started/gdextension.html). Custom engine builds are not necessary. - **GDExtension:** LimboAI can be [used as extension](https://limboai.readthedocs.io/en/stable/getting-started/gdextension.html). Custom engine builds are not necessary.
- **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 ## 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. Follow the [First steps](https://limboai.readthedocs.io/en/stable/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/stable/getting-started/gdextension.html).
### Precompiled builds ### Precompiled builds
@ -88,25 +93,31 @@ LimboAI can be used as either a C++ module or as a GDExtension shared library. G
### Compiling from source ### Compiling from source
>**🛈 For GDExtension:** Refer to comments in [setup_gdextension.sh](./gdextension/setup_gdextension.sh) file.
- Download the Godot Engine source code and put this module source into the `modules/limboai` directory. - Download the Godot Engine source code and put this module source into the `modules/limboai` directory.
- Consult the Godot Engine documentation for instructions on [how to build from source code](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html). - Consult the Godot Engine documentation for instructions on [how to build from source code](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html).
- If you plan to export a game utilizing the LimboAI module, you'll also need to build export templates. - If you plan to export a game utilizing the LimboAI module, you'll also need to build export templates.
- To execute unit tests, compile the engine with `tests=yes` and run it with `--test --tc="*[LimboAI]*"`. - To execute unit tests, compile the engine with `tests=yes` and run it with `--test --tc="*[LimboAI]*"`.
#### For GDExtension
- You'll need SCons build tool and a C++ compiler. See also [Compiling](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html).
- Run `scons target=editor` to build the plugin library for your current platform.
- SCons will automatically clone the godot-cpp/ repository if it doesn't already exist in the `limboai/godot-cpp` directory.
- By default, built targets are placed in the demo project: `demo/addons/limboai/bin/`
- Check `scons -h` for other options and targets.
## Using the plugin ## Using the plugin
- [Online Documentation](https://limboai.readthedocs.io/en/latest/index.html) - Online Documentation: [stable](https://limboai.readthedocs.io/en/stable/index.html), [latest](https://limboai.readthedocs.io/en/latest/index.html)
- [First steps](https://limboai.readthedocs.io/en/latest/index.html#first-steps) - [First steps](https://limboai.readthedocs.io/en/stable/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/stable/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/stable/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/stable/getting-started/using-blackboard.html)
- [Accessing nodes in the scene tree](https://limboai.readthedocs.io/en/latest/getting-started/accessing-nodes.html) - [Accessing nodes in the scene tree](https://limboai.readthedocs.io/en/stable/getting-started/accessing-nodes.html)
- [State machines](https://limboai.readthedocs.io/en/latest/getting-started/hsm.html) - [State machines](https://limboai.readthedocs.io/en/stable/getting-started/hsm.html)
- [Using GDExtension](https://limboai.readthedocs.io/en/latest/getting-started/gdextension.html) - [Using GDExtension](https://limboai.readthedocs.io/en/stable/getting-started/gdextension.html)
- [Using LimboAI with C#](https://limboai.readthedocs.io/en/latest/getting-started/c-sharp.html) - [Using LimboAI with C#](https://limboai.readthedocs.io/en/stable/getting-started/c-sharp.html)
- [Class reference](https://limboai.readthedocs.io/en/latest/getting-started/featured-classes.html) - [Class reference](https://limboai.readthedocs.io/en/stable/getting-started/featured-classes.html)
## Contributing ## Contributing
@ -122,4 +133,6 @@ I write about LimboAI development on Mastodon: https://mastodon.gamedev.place/@l
## 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
LimboAI logo and demo project art assets are licensed under the Creative Commons Attribution 4.0 International license that can be found at https://creativecommons.org/licenses/by/4.0/

160
SConstruct Normal file
View File

@ -0,0 +1,160 @@
#!/usr/bin/env python
"""
This is SConstruct file for building GDExtension variant using SCons build system.
For module variant, see SCsub file.
Use --project=DIR to customize output path for built targets.
- Built targets are placed into "DIR/addons/limboai/bin".
- For example: scons --project="../my_project"
- built targets will be placed into "../my_project/addons/limboai/bin".
- If not specified, built targets are put into the demo/ project.
"""
import os
import sys
import subprocess
from limboai_version import generate_module_version_header, godot_cpp_ref
sys.path.append("gdextension")
from update_icon_entries import update_icon_entries
from fix_icon_imports import fix_icon_imports
# Check if godot-cpp/ exists
if not os.path.exists("godot-cpp"):
print("Directory godot-cpp/ not found. Cloning repository...")
result = subprocess.run(
["git", "clone", "-b", godot_cpp_ref, "https://github.com/godotengine/godot-cpp.git"],
check=True,
# capture_output=True
)
if result.returncode != 0:
print("Error: Cloning godot-cpp repository failed.")
Exit(1)
print("Finished cloning godot-cpp repository.")
AddOption(
"--project",
dest="project",
type="string",
nargs=1,
action="store",
metavar="DIR",
default="demo",
help="Specify project directory",
)
help_text = """
Options:
--project=DIR Specify project directory (default: "demo");
built targets will be placed in DIR/addons/limboai/bin
"""
Help(help_text)
project_dir = GetOption("project")
if not os.path.isdir(project_dir):
print("Project directory not found: " + project_dir)
Exit(2)
# Parse LimboAI-specific variables.
vars = Variables()
vars.AddVariables(
BoolVariable("deploy_manifest", help="Deploy limboai.gdextension into PROJECT/addons/limboai/bin", default=True),
BoolVariable("deploy_icons", help="Deploy icons into PROJECT/addons/limboai/icons", default=True),
)
env = Environment(tools=["default"], PLATFORM="", variables=vars)
Help(vars.GenerateHelpText(env))
# Read LimboAI-specific variables.
deploy_manifest = env["deploy_manifest"]
deploy_icons = env["deploy_icons"]
# Remove processed variables from ARGUMENTS to avoid godot-cpp warnings.
for o in vars.options:
if o.key in ARGUMENTS:
del ARGUMENTS[o.key]
# For reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags
env = SConscript("godot-cpp/SConstruct")
# Generate version header.
print("Generating LimboAI version header...")
generate_module_version_header()
# Update icon entries in limboai.gdextension file.
# Note: This will remove everything after [icons] section, and rebuild it with generated icon entries.
print("Updating LimboAI icon entries...")
update_icon_entries(silent=True)
# Fix icon imports in the PROJECT/addons/limboai/icons/.
# Enables scaling and color conversion in the editor for imported SVG icons.
try:
fix_icon_imports(project_dir)
except FileNotFoundError as e:
print(e)
except Exception as e:
print("Unknown error: " + str(e))
# Tweak this if you want to use different folders, or more folders, to store your source code in.
env.Append(CPPDEFINES=["LIMBOAI_GDEXTENSION"])
sources = Glob("*.cpp")
sources += Glob("blackboard/*.cpp")
sources += Glob("blackboard/bb_param/*.cpp")
sources += Glob("bt/*.cpp")
sources += Glob("bt/tasks/*.cpp")
sources += Glob("bt/tasks/blackboard/*.cpp")
sources += Glob("bt/tasks/composites/*.cpp")
sources += Glob("bt/tasks/decorators/*.cpp")
sources += Glob("bt/tasks/scene/*.cpp")
sources += Glob("bt/tasks/utility/*.cpp")
sources += Glob("gdextension/*.cpp")
sources += Glob("editor/debugger/*.cpp")
sources += Glob("editor/*.cpp")
sources += Glob("hsm/*.cpp")
sources += Glob("util/*.cpp")
# Generate documentation header.
if env["target"] in ["editor", "template_debug"]:
doc_data = env.GodotCPPDocData("gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
sources.append(doc_data)
# Build library.
if env["platform"] == "macos":
library = env.SharedLibrary(
project_dir
+ "/addons/limboai/bin/liblimboai.{}.{}.framework/liblimboai.{}.{}".format(
env["platform"], env["target"], env["platform"], env["target"]
),
source=sources,
)
else:
library = env.SharedLibrary(
project_dir + "/addons/limboai/bin/liblimboai{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
source=sources,
)
Default(library)
# Deploy icons into PROJECT/addons/limboai/icons.
if deploy_icons:
cmd_deploy_icons = env.Command(
project_dir + "/addons/limboai/icons/",
"icons/",
Copy("$TARGET", "$SOURCE"),
)
Default(cmd_deploy_icons)
# Deploy limboai.gdextension into PROJECT/addons/limboai/bin.
if deploy_manifest:
cmd_deploy_manifest = env.Command(
project_dir + "/addons/limboai/bin/limboai.gdextension",
"gdextension/limboai.gdextension",
Copy("$TARGET", "$SOURCE"),
)
Default(cmd_deploy_manifest)

View File

@ -11,15 +11,6 @@
#include "bb_node.h" #include "bb_node.h"
#ifdef LIMBOAI_MODULE
#include "core/error/error_macros.h"
#include "scene/main/node.h"
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/node.hpp>
#endif // LIMBOAI_GDEXTENSION
Variant BBNode::get_value(Node *p_scene_root, 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_NULL_V_MSG(p_scene_root, Variant(), "BBNode: get_value() failed - scene_root is null."); ERR_FAIL_NULL_V_MSG(p_scene_root, Variant(), "BBNode: get_value() failed - scene_root is null.");
ERR_FAIL_NULL_V_MSG(p_blackboard, Variant(), "BBNode: get_value() failed - blackboard is null."); ERR_FAIL_NULL_V_MSG(p_blackboard, Variant(), "BBNode: get_value() failed - blackboard is null.");
@ -33,13 +24,10 @@ Variant BBNode::get_value(Node *p_scene_root, const Ref<Blackboard> &p_blackboar
if (val.get_type() == Variant::NODE_PATH) { if (val.get_type() == Variant::NODE_PATH) {
return p_scene_root->get_node_or_null(val); return p_scene_root->get_node_or_null(val);
} else if (val.get_type() == Variant::OBJECT || val.get_type() == Variant::NIL) {
return val;
} else { } else {
Object *obj = val; WARN_PRINT("BBNode: Unexpected variant type: " + Variant::get_type_name(val.get_type()) + ". Returning default value.");
if (unlikely(obj == nullptr && val.get_type() != Variant::NIL)) {
WARN_PRINT("BBNode: Unexpected variant type of a blackboard variable.");
return p_default; return p_default;
} else {
return obj;
}
} }
} }

View File

@ -25,7 +25,7 @@ void BBVariable::set_value(const Variant &p_value) {
data->value_changed = true; data->value_changed = true;
if (is_bound()) { if (is_bound()) {
Object *obj = ObjectDB::get_instance(ObjectID(data->bound_object)); Object *obj = OBJECT_DB_GET_INSTANCE(data->bound_object);
ERR_FAIL_COND_MSG(!obj, "Blackboard: Failed to get bound object."); ERR_FAIL_COND_MSG(!obj, "Blackboard: Failed to get bound object.");
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
bool r_valid; bool r_valid;
@ -39,7 +39,7 @@ void BBVariable::set_value(const Variant &p_value) {
Variant BBVariable::get_value() const { Variant BBVariable::get_value() const {
if (is_bound()) { if (is_bound()) {
Object *obj = ObjectDB::get_instance(ObjectID(data->bound_object)); Object *obj = OBJECT_DB_GET_INSTANCE(data->bound_object);
ERR_FAIL_COND_V_MSG(!obj, data->value, "Blackboard: Failed to get bound object."); ERR_FAIL_COND_V_MSG(!obj, data->value, "Blackboard: Failed to get bound object.");
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
bool r_valid; bool r_valid;

View File

@ -40,6 +40,10 @@ private:
protected: protected:
static void _bind_methods(); static void _bind_methods();
#ifdef LIMBOAI_GDEXTENSION
String _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }
#endif
public: public:
void set_parent(const Ref<Blackboard> &p_blackboard) { parent = p_blackboard; } void set_parent(const Ref<Blackboard> &p_blackboard) { parent = p_blackboard; }
Ref<Blackboard> get_parent() const { return parent; } Ref<Blackboard> get_parent() const { return parent; }
@ -49,6 +53,7 @@ public:
Variant get_var(const StringName &p_name, const Variant &p_default = Variant(), 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;
_FORCE_INLINE_ bool has_local_var(const StringName &p_name) const { return data.has(p_name); }
void erase_var(const StringName &p_name); void erase_var(const StringName &p_name);
void clear() { data.clear(); } void clear() { data.clear(); }
TypedArray<StringName> list_vars() const; TypedArray<StringName> list_vars() const;

View File

@ -387,46 +387,50 @@ void BlackboardPlan::sync_with_base_plan() {
} }
} }
// Add a variable duplicate to the blackboard, optionally with NodePath prefetch. Ref<Blackboard> BlackboardPlan::create_blackboard(Node *p_prefetch_root, const Ref<Blackboard> &p_parent_scope, Node *p_prefetch_root_for_base_plan) {
inline void bb_add_var_dup_with_prefetch(const Ref<Blackboard> &p_blackboard, const StringName &p_name, const BBVariable &p_var, bool p_prefetch, Node *p_node) { ERR_FAIL_COND_V(p_prefetch_root == nullptr && prefetch_nodepath_vars, memnew(Blackboard));
if (unlikely(p_prefetch && p_var.get_type() == Variant::NODE_PATH)) {
Node *n = p_node->get_node_or_null(p_var.get_value());
BBVariable var = p_var.duplicate(true);
if (n != nullptr) {
var.set_value(n);
} else {
if (p_blackboard->has_var(p_name)) {
// Not adding: Assuming variable was initialized by the user or in the parent scope.
return;
}
ERR_PRINT(vformat("BlackboardPlan: Prefetch failed for variable $%s with value: %s", p_name, p_var.get_value()));
var.set_value(Variant());
}
p_blackboard->assign_var(p_name, var);
} else {
p_blackboard->assign_var(p_name, p_var.duplicate(true));
}
}
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));
Ref<Blackboard> bb = memnew(Blackboard); Ref<Blackboard> bb = memnew(Blackboard);
bb->set_parent(p_parent_scope); bb->set_parent(p_parent_scope);
populate_blackboard(bb, true, p_node); populate_blackboard(bb, true, p_prefetch_root, p_prefetch_root_for_base_plan);
return bb; return bb;
} }
void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite, Node *p_node) { void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite, Node *p_prefetch_root, Node *p_prefetch_root_for_base_plan) {
ERR_FAIL_COND(p_node == nullptr && prefetch_nodepath_vars); ERR_FAIL_COND(p_prefetch_root == nullptr && prefetch_nodepath_vars);
ERR_FAIL_COND(p_blackboard.is_null());
for (const Pair<StringName, BBVariable> &p : var_list) { for (const Pair<StringName, BBVariable> &p : var_list) {
if (p_blackboard->has_var(p.first) && !overwrite) { if (p_blackboard->has_local_var(p.first) && !overwrite) {
#ifdef DEBUG_ENABLED
Variant::Type existing_type = p_blackboard->get_var(p.first).get_type();
Variant::Type planned_type = p.second.get_type();
if (existing_type != planned_type && existing_type != Variant::NIL && planned_type != Variant::NIL && !(existing_type == Variant::OBJECT && planned_type == Variant::NODE_PATH)) {
WARN_PRINT(vformat("BlackboardPlan: Not overwriting %s as it already exists in the blackboard, but it has a different type than planned (%s vs %s). File: %s",
LimboUtility::get_singleton()->decorate_var(p.first), Variant::get_type_name(existing_type), Variant::get_type_name(planned_type), get_path()));
}
#endif
continue; continue;
} }
bb_add_var_dup_with_prefetch(p_blackboard, p.first, p.second, prefetch_nodepath_vars, p_node); bool has_mapping = parent_scope_mapping.has(p.first);
if (parent_scope_mapping.has(p.first)) { bool do_prefetch = !has_mapping && prefetch_nodepath_vars;
// Add a variable duplicate to the blackboard, optionally with NodePath prefetch.
BBVariable var = p.second.duplicate(true);
if (unlikely(do_prefetch && p.second.get_type() == Variant::NODE_PATH)) {
Node *prefetch_root = !p_prefetch_root_for_base_plan || !is_derived() || is_derived_var_changed(p.first) ? p_prefetch_root : p_prefetch_root_for_base_plan;
Node *n = prefetch_root->get_node_or_null(p.second.get_value());
if (n != nullptr) {
var.set_value(n);
} else {
ERR_PRINT(vformat("BlackboardPlan: Prefetch failed for variable $%s with value: %s", p.first, p.second.get_value()));
var.set_value(Variant());
}
}
p_blackboard->assign_var(p.first, var);
if (has_mapping) {
StringName target_var = parent_scope_mapping[p.first]; StringName target_var = parent_scope_mapping[p.first];
if (target_var != StringName()) { 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)); ERR_CONTINUE_MSG(p_blackboard->get_parent() == nullptr, vformat("BlackboardPlan: Cannot link variable %s to parent scope because the parent scope is not set.", LimboUtility::get_singleton()->decorate_var(p.first)));
p_blackboard->link_var(p.first, p_blackboard->get_parent(), target_var); p_blackboard->link_var(p.first, p_blackboard->get_parent(), target_var);
} }
} }
@ -443,8 +447,8 @@ void BlackboardPlan::_bind_methods() {
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("set_parent_scope_plan_provider", "callable"), &BlackboardPlan::set_parent_scope_plan_provider); 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("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("create_blackboard", "prefetch_root", "parent_scope", "prefetch_root_for_base_plan"), &BlackboardPlan::create_blackboard, DEFVAL(Ref<Blackboard>()), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite", "node"), &BlackboardPlan::populate_blackboard); ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite", "prefetch_root", "prefetch_root_for_base_plan"), &BlackboardPlan::populate_blackboard, DEFVAL(Variant()));
// 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.
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefetch_nodepath_vars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_prefetch_nodepath_vars", "is_prefetching_nodepath_vars"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefetch_nodepath_vars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_prefetch_nodepath_vars", "is_prefetching_nodepath_vars");

View File

@ -55,6 +55,10 @@ protected:
bool _property_can_revert(const StringName &p_name) const; bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const; bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
#ifdef LIMBOAI_GDEXTENSION
String _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }
#endif
public: 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; }
@ -84,9 +88,10 @@ 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(); }
_FORCE_INLINE_ bool is_derived_var_changed(const StringName &p_name) const { return base.is_valid() && var_map.has(p_name) && var_map[p_name].is_value_changed(); }
Ref<Blackboard> create_blackboard(Node *p_agent, const Ref<Blackboard> &p_parent_scope = Ref<Blackboard>()); Ref<Blackboard> create_blackboard(Node *p_prefetch_root, const Ref<Blackboard> &p_parent_scope = Ref<Blackboard>(), Node *p_prefetch_root_for_base_plan = nullptr);
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_prefetch_root, Node *p_prefetch_root_for_base_plan = nullptr);
BlackboardPlan(); BlackboardPlan();
}; };

View File

@ -77,13 +77,16 @@ 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, Node *p_scene_root) const { Ref<BTInstance> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_instance_owner, Node *p_custom_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, nullptr, "BehaviorTree: Instantiation failed - BT has 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_agent, nullptr, "BehaviorTree: Instantiation failed - agent can't be null.");
ERR_FAIL_NULL_V_MSG(p_scene_root, memnew(BTTask), "Trying to instance a behavior tree with no valid scene root."); ERR_FAIL_NULL_V_MSG(p_instance_owner, nullptr, "BehaviorTree: Instantiation failed -- instance owner can't be null.");
Ref<BTTask> inst = root_task->clone(); ERR_FAIL_NULL_V_MSG(p_blackboard, nullptr, "BehaviorTree: Instantiation failed - blackboard can't be null.");
inst->initialize(p_agent, p_blackboard, p_scene_root); Node *scene_root = p_custom_scene_root ? p_custom_scene_root : p_instance_owner->get_owner();
return inst; ERR_FAIL_NULL_V_MSG(scene_root, nullptr, "BehaviorTree: Instantiation failed - unable to establish scene root. This is likely due to the instance owner not being owned by a scene node and custom_scene_root being null.");
Ref<BTTask> root_copy = root_task->clone();
root_copy->initialize(p_agent, p_blackboard, scene_root);
return BTInstance::create(root_copy, get_path(), p_instance_owner);
} }
void BehaviorTree::_plan_changed() { void BehaviorTree::_plan_changed() {
@ -116,7 +119,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", "scene_root"), &BehaviorTree::instantiate); ClassDB::bind_method(D_METHOD("instantiate", "agent", "blackboard", "instance_owner", "custom_scene_root"), &BehaviorTree::instantiate, DEFVAL(Variant()));
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");

View File

@ -13,6 +13,7 @@
#define BEHAVIOR_TREE_H #define BEHAVIOR_TREE_H
#include "../blackboard/blackboard_plan.h" #include "../blackboard/blackboard_plan.h"
#include "bt_instance.h"
#include "tasks/bt_task.h" #include "tasks/bt_task.h"
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
@ -42,6 +43,10 @@ private:
protected: protected:
static void _bind_methods(); static void _bind_methods();
#ifdef LIMBOAI_GDEXTENSION
String _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }
#endif
public: public:
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
virtual bool editor_can_reload_from_file() override { return false; } virtual bool editor_can_reload_from_file() override { return false; }
@ -58,7 +63,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, Node *p_scene_root) const; Ref<BTInstance> instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_instance_owner, Node *p_custom_scene_root = nullptr) const;
BehaviorTree(); BehaviorTree();
~BehaviorTree(); ~BehaviorTree();

154
bt/bt_instance.cpp Normal file
View File

@ -0,0 +1,154 @@
/**
* bt_instance.cpp
* =============================================================================
* Copyright 2021-2024 Serhii Snitsaruk
*
* 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.
* =============================================================================
*/
#include "bt_instance.h"
#include "../editor/debugger/limbo_debugger.h"
#include "behavior_tree.h"
#ifdef LIMBOAI_MODULE
#include "core/os/time.h"
#include "main/performance.h"
#endif
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/performance.hpp>
#include <godot_cpp/classes/time.hpp>
#endif
Ref<BTInstance> BTInstance::create(Ref<BTTask> p_root_task, String p_source_bt_path, Node *p_owner_node) {
ERR_FAIL_NULL_V(p_root_task, nullptr);
ERR_FAIL_NULL_V(p_owner_node, nullptr);
Ref<BTInstance> inst;
inst.instantiate();
inst->root_task = p_root_task;
inst->owner_node_id = p_owner_node->get_instance_id();
inst->source_bt_path = p_source_bt_path;
return inst;
}
BT::Status BTInstance::update(double p_delta) {
ERR_FAIL_COND_V(!root_task.is_valid(), BT::FRESH);
#ifdef DEBUG_ENABLED
double start = Time::get_singleton()->get_ticks_usec();
#endif
last_status = root_task->execute(p_delta);
emit_signal(LW_NAME(updated), last_status);
#ifdef DEBUG_ENABLED
double end = Time::get_singleton()->get_ticks_usec();
update_time_acc += (end - start);
update_time_n += 1.0;
#endif
return last_status;
}
void BTInstance::set_monitor_performance(bool p_monitor) {
#ifdef DEBUG_ENABLED
monitor_performance = p_monitor;
if (monitor_performance) {
_add_custom_monitor();
} else {
_remove_custom_monitor();
}
#endif
}
bool BTInstance::get_monitor_performance() const {
#ifdef DEBUG_ENABLED
return monitor_performance;
#else
return false;
#endif
}
void BTInstance::register_with_debugger() {
#ifdef DEBUG_ENABLED
if (LimboDebugger::get_singleton()->is_active()) {
LimboDebugger::get_singleton()->register_bt_instance(get_instance_id());
}
#endif
}
void BTInstance::unregister_with_debugger() {
#ifdef DEBUG_ENABLED
if (LimboDebugger::get_singleton()->is_active()) {
LimboDebugger::get_singleton()->unregister_bt_instance(get_instance_id());
}
#endif
}
#ifdef DEBUG_ENABLED
double BTInstance::_get_mean_update_time_msec_and_reset() {
if (update_time_n) {
double mean_time_msec = (update_time_acc * 0.001) / update_time_n;
update_time_acc = 0.0;
update_time_n = 0.0;
return mean_time_msec;
}
return 0.0;
}
void BTInstance::_add_custom_monitor() {
ERR_FAIL_NULL(get_owner_node());
ERR_FAIL_NULL(root_task);
ERR_FAIL_NULL(root_task->get_agent());
if (monitor_id == StringName()) {
monitor_id = vformat("LimboAI/update_ms|%s_%s_%s", root_task->get_agent()->get_name(), get_owner_node()->get_name(),
String(itos(get_instance_id())).md5_text().substr(0, 4));
}
if (!Performance::get_singleton()->has_custom_monitor(monitor_id)) {
PERFORMANCE_ADD_CUSTOM_MONITOR(monitor_id, callable_mp(this, &BTInstance::_get_mean_update_time_msec_and_reset));
}
}
void BTInstance::_remove_custom_monitor() {
if (monitor_id != StringName() && Performance::get_singleton()->has_custom_monitor(monitor_id)) {
Performance::get_singleton()->remove_custom_monitor(monitor_id);
}
}
#endif // * DEBUG_ENABLED
void BTInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_root_task"), &BTInstance::get_root_task);
ClassDB::bind_method(D_METHOD("get_owner_node"), &BTInstance::get_owner_node);
ClassDB::bind_method(D_METHOD("get_last_status"), &BTInstance::get_last_status);
ClassDB::bind_method(D_METHOD("get_source_bt_path"), &BTInstance::get_source_bt_path);
ClassDB::bind_method(D_METHOD("get_agent"), &BTInstance::get_agent);
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTInstance::get_blackboard);
ClassDB::bind_method(D_METHOD("is_instance_valid"), &BTInstance::is_instance_valid);
ClassDB::bind_method(D_METHOD("set_monitor_performance", "monitor"), &BTInstance::set_monitor_performance);
ClassDB::bind_method(D_METHOD("get_monitor_performance"), &BTInstance::get_monitor_performance);
ClassDB::bind_method(D_METHOD("update", "delta"), &BTInstance::update);
ClassDB::bind_method(D_METHOD("register_with_debugger"), &BTInstance::register_with_debugger);
ClassDB::bind_method(D_METHOD("unregister_with_debugger"), &BTInstance::unregister_with_debugger);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitor_performance"), "set_monitor_performance", "get_monitor_performance");
ADD_SIGNAL(MethodInfo("updated", PropertyInfo(Variant::INT, "status")));
ADD_SIGNAL(MethodInfo("freed"));
}
BTInstance::~BTInstance() {
emit_signal(LW_NAME(freed));
#ifdef DEBUG_ENABLED
_remove_custom_monitor();
#endif
}

68
bt/bt_instance.h Normal file
View File

@ -0,0 +1,68 @@
/**
* bt_instance.h
* =============================================================================
* Copyright 2021-2024 Serhii Snitsaruk
*
* 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.
* =============================================================================
*/
#ifndef BT_INSTANCE_H
#define BT_INSTANCE_H
#include "tasks/bt_task.h"
class BTInstance : public RefCounted {
GDCLASS(BTInstance, RefCounted);
private:
Ref<BTTask> root_task;
uint64_t owner_node_id = 0;
String source_bt_path;
BT::Status last_status = BT::FRESH;
#ifdef DEBUG_ENABLED
bool monitor_performance = false;
StringName monitor_id;
double update_time_acc = 0.0;
double update_time_n = 0.0;
double _get_mean_update_time_msec_and_reset();
void _add_custom_monitor();
void _remove_custom_monitor();
#endif // * DEBUG_ENABLED
protected:
static void _bind_methods();
#ifdef LIMBOAI_GDEXTENSION
String _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }
#endif
public:
_FORCE_INLINE_ Ref<BTTask> get_root_task() const { return root_task; }
_FORCE_INLINE_ Node *get_owner_node() const { return owner_node_id ? Object::cast_to<Node>(OBJECT_DB_GET_INSTANCE(owner_node_id)) : nullptr; }
_FORCE_INLINE_ BT::Status get_last_status() const { return last_status; }
_FORCE_INLINE_ String get_source_bt_path() const { return source_bt_path; }
_FORCE_INLINE_ Node *get_agent() const { return root_task.is_valid() ? root_task->get_agent() : nullptr; }
_FORCE_INLINE_ Ref<Blackboard> get_blackboard() const { return root_task.is_valid() ? root_task->get_blackboard() : Ref<Blackboard>(); }
_FORCE_INLINE_ bool is_instance_valid() const { return root_task.is_valid(); }
BT::Status update(double p_delta);
void set_monitor_performance(bool p_monitor);
bool get_monitor_performance() const;
void register_with_debugger();
void unregister_with_debugger();
static Ref<BTInstance> create(Ref<BTTask> p_root_task, String p_source_bt_path, Node *p_owner_node);
BTInstance() = default;
~BTInstance();
};
#endif // BT_INSTANCE_H

View File

@ -11,7 +11,6 @@
#include "bt_player.h" #include "bt_player.h"
#include "../editor/debugger/limbo_debugger.h"
#include "../util/limbo_compat.h" #include "../util/limbo_compat.h"
#include "../util/limbo_string_names.h" #include "../util/limbo_string_names.h"
@ -44,24 +43,20 @@
VARIANT_ENUM_CAST(BTPlayer::UpdateMode); VARIANT_ENUM_CAST(BTPlayer::UpdateMode);
void BTPlayer::_load_tree() { void BTPlayer::_load_tree() {
#ifdef DEBUG_ENABLED bt_instance.unref();
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
LimboDebugger::get_singleton()->unregister_bt_instance(tree_instance, get_path());
}
#endif
tree_instance.unref();
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer: Initialization failed - 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: Initialization failed - 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.");
Node *agent = GET_NODE(this, agent_node); 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)); ERR_FAIL_NULL_MSG(agent, vformat("BTPlayer: Initialization failed - can't get agent with path '%s'.", agent_node));
Node *scene_root = get_owner(); Node *scene_root = _get_scene_root();
ERR_FAIL_NULL_MSG(scene_root, "BTPlayer: Initialization failed - can't get scene root (make sure the BTPlayer's owner property is set)."); ERR_FAIL_COND_MSG(scene_root == nullptr,
tree_instance = behavior_tree->instantiate(agent, blackboard, scene_root); "BTPlayer: Initialization failed - unable to establish scene root. This is likely due to BTPlayer not being owned by a scene node. Check BTPlayer.set_scene_root_hint().");
bt_instance = behavior_tree->instantiate(agent, blackboard, this, scene_root);
ERR_FAIL_COND_MSG(bt_instance.is_null(), "BTPlayer: Failed to instantiate behavior tree.");
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (IS_DEBUGGER_ACTIVE()) { bt_instance->set_monitor_performance(monitor_performance);
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path()); bt_instance->register_with_debugger();
} #endif // DEBUG_ENABLED
#endif
} }
void BTPlayer::_update_blackboard_plan() { void BTPlayer::_update_blackboard_plan() {
@ -75,6 +70,27 @@ void BTPlayer::_update_blackboard_plan() {
blackboard_plan->set_base_plan(behavior_tree.is_valid() ? behavior_tree->get_blackboard_plan() : nullptr); blackboard_plan->set_base_plan(behavior_tree.is_valid() ? behavior_tree->get_blackboard_plan() : nullptr);
} }
void BTPlayer::set_bt_instance(const Ref<BTInstance> &p_bt_instance) {
ERR_FAIL_COND_MSG(p_bt_instance.is_null(), "BTPlayer: Failed to set behavior tree instance - instance is null.");
ERR_FAIL_COND_MSG(!p_bt_instance->is_instance_valid(), "BTPlayer: Failed to set behavior tree instance - instance is not valid.");
bt_instance = p_bt_instance;
blackboard = p_bt_instance->get_blackboard();
agent_node = p_bt_instance->get_agent()->get_path();
blackboard_plan.unref();
behavior_tree.unref();
}
void BTPlayer::set_scene_root_hint(Node *p_scene_root) {
ERR_FAIL_NULL_MSG(p_scene_root, "BTPlayer: Failed to set scene root hint - scene root is null.");
if (bt_instance.is_valid()) {
ERR_PRINT("BTPlayer: Scene root hint shouldn't be set after the behavior tree is instantiated. This change will not affect the current behavior tree instance.");
}
scene_root_hint = p_scene_root;
}
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) { void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
if (Engine::get_singleton()->is_editor_hint()) { if (Engine::get_singleton()->is_editor_hint()) {
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) { if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) {
@ -87,7 +103,7 @@ void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
_update_blackboard_plan(); _update_blackboard_plan();
} else { } else {
behavior_tree = p_tree; behavior_tree = p_tree;
if (get_owner()) { if (get_owner() && is_inside_tree()) {
_load_tree(); _load_tree();
} }
} }
@ -95,7 +111,7 @@ void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
void BTPlayer::set_agent_node(const NodePath &p_agent_node) { void BTPlayer::set_agent_node(const NodePath &p_agent_node) {
agent_node = p_agent_node; agent_node = p_agent_node;
if (tree_instance.is_valid()) { if (bt_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."); ERR_PRINT("BTPlayer: Agent node cannot be set after the behavior tree is instantiated. This change will not affect the behavior tree instance.");
} }
} }
@ -119,80 +135,38 @@ void BTPlayer::set_active(bool p_active) {
} }
void BTPlayer::update(double p_delta) { void BTPlayer::update(double p_delta) {
if (!tree_instance.is_valid()) { if (!bt_instance.is_valid()) {
ERR_PRINT_ONCE(vformat("BTPlayer doesn't have a behavior tree with a valid root task to execute (owner: %s)", get_owner())); ERR_PRINT_ONCE(vformat("BTPlayer doesn't have a behavior tree with a valid root task to execute (owner: %s)", get_owner()));
return; return;
} }
#ifdef DEBUG_ENABLED
double start = GET_TICKS_USEC();
#endif
if (active) { if (active) {
last_status = tree_instance->execute(p_delta); BT::Status status = bt_instance->update(p_delta);
emit_signal(LimboStringNames::get_singleton()->updated, last_status); emit_signal(LW_NAME(updated), status);
if (last_status == BTTask::SUCCESS || last_status == BTTask::FAILURE) { #ifndef DISABLE_DEPRECATED
emit_signal(LimboStringNames::get_singleton()->behavior_tree_finished, last_status); if (status == BTTask::SUCCESS || status == BTTask::FAILURE) {
emit_signal(LW_NAME(behavior_tree_finished), status);
} }
#endif // DISABLE_DEPRECATED
} }
#ifdef DEBUG_ENABLED
double end = GET_TICKS_USEC();
update_time_acc += (end - start);
update_time_n += 1.0;
#endif
} }
void BTPlayer::restart() { void BTPlayer::restart() {
tree_instance->abort(); ERR_FAIL_COND_MSG(bt_instance.is_null(), "BTPlayer: Restart failed - no valid tree instance. Make sure the BTPlayer has a valid behavior tree with a valid root task.");
bt_instance->get_root_task()->abort();
set_active(true); set_active(true);
} }
#ifdef DEBUG_ENABLED 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() && monitor_performance) { #ifdef DEBUG_ENABLED
// Don't add custom monitor if not in scene. if (bt_instance.is_valid()) {
return; bt_instance->set_monitor_performance(monitor_performance);
}
if (monitor_performance) {
_add_custom_monitor();
} else {
_remove_custom_monitor();
} }
#endif
} }
void BTPlayer::_add_custom_monitor() {
if (monitor_id == StringName()) {
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));
}
if (!Performance::get_singleton()->has_custom_monitor(monitor_id)) {
PERFORMANCE_ADD_CUSTOM_MONITOR(monitor_id, callable_mp(this, &BTPlayer::_get_mean_update_time_msec));
}
}
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);
}
}
double BTPlayer::_get_mean_update_time_msec() {
if (update_time_n) {
double mean_time_msec = (update_time_acc * 0.001) / update_time_n;
update_time_acc = 0.0;
update_time_n = 0.0;
return mean_time_msec;
}
return 0.0;
}
#endif // ! DEBUG_ENABLED
void BTPlayer::_notification(int p_notification) { void BTPlayer::_notification(int p_notification) {
switch (p_notification) { switch (p_notification) {
case NOTIFICATION_PROCESS: { case NOTIFICATION_PROCESS: {
@ -209,7 +183,8 @@ void BTPlayer::_notification(int p_notification) {
blackboard = Ref<Blackboard>(memnew(Blackboard)); blackboard = Ref<Blackboard>(memnew(Blackboard));
} }
if (blackboard_plan.is_valid()) { if (blackboard_plan.is_valid()) {
blackboard_plan->populate_blackboard(blackboard, false, this); // Don't overwrite existing blackboard values as they may be initialized from code.
blackboard_plan->populate_blackboard(blackboard, false, this, _get_scene_root());
} }
if (behavior_tree.is_valid()) { if (behavior_tree.is_valid()) {
_load_tree(); _load_tree();
@ -221,21 +196,17 @@ void BTPlayer::_notification(int p_notification) {
} break; } break;
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) { if (bt_instance.is_valid()) {
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path()); bt_instance->set_monitor_performance(monitor_performance);
} bt_instance->register_with_debugger();
if (monitor_performance) {
_add_custom_monitor();
} }
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
} break; } break;
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) { if (bt_instance.is_valid()) {
LimboDebugger::get_singleton()->unregister_bt_instance(tree_instance, get_path()); bt_instance->set_monitor_performance(false);
} bt_instance->unregister_with_debugger();
if (monitor_performance) {
_remove_custom_monitor();
} }
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
@ -263,11 +234,16 @@ void BTPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blackboard_plan", "plan"), &BTPlayer::set_blackboard_plan); ClassDB::bind_method(D_METHOD("set_blackboard_plan", "plan"), &BTPlayer::set_blackboard_plan);
ClassDB::bind_method(D_METHOD("get_blackboard_plan"), &BTPlayer::get_blackboard_plan); ClassDB::bind_method(D_METHOD("get_blackboard_plan"), &BTPlayer::get_blackboard_plan);
ClassDB::bind_method(D_METHOD("set_monitor_performance", "enable"), &BTPlayer::set_monitor_performance);
ClassDB::bind_method(D_METHOD("get_monitor_performance"), &BTPlayer::get_monitor_performance);
ClassDB::bind_method(D_METHOD("update", "delta"), &BTPlayer::update); ClassDB::bind_method(D_METHOD("update", "delta"), &BTPlayer::update);
ClassDB::bind_method(D_METHOD("restart"), &BTPlayer::restart); ClassDB::bind_method(D_METHOD("restart"), &BTPlayer::restart);
ClassDB::bind_method(D_METHOD("get_last_status"), &BTPlayer::get_last_status);
ClassDB::bind_method(D_METHOD("get_tree_instance"), &BTPlayer::get_tree_instance); ClassDB::bind_method(D_METHOD("get_bt_instance"), &BTPlayer::get_bt_instance);
ClassDB::bind_method(D_METHOD("set_bt_instance", "bt_instance"), &BTPlayer::set_bt_instance);
ClassDB::bind_method(D_METHOD("set_scene_root_hint", "scene_root"), &BTPlayer::set_scene_root_hint);
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::NODE_PATH, "agent_node"), "set_agent_node", "get_agent_node");
@ -275,19 +251,17 @@ void BTPlayer::_bind_methods() {
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");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT | PROPERTY_USAGE_ALWAYS_DUPLICATE), "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 | PROPERTY_USAGE_ALWAYS_DUPLICATE), "set_blackboard_plan", "get_blackboard_plan");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitor_performance"), "set_monitor_performance", "get_monitor_performance");
BIND_ENUM_CONSTANT(IDLE); BIND_ENUM_CONSTANT(IDLE);
BIND_ENUM_CONSTANT(PHYSICS); BIND_ENUM_CONSTANT(PHYSICS);
BIND_ENUM_CONSTANT(MANUAL); BIND_ENUM_CONSTANT(MANUAL);
ADD_SIGNAL(MethodInfo("behavior_tree_finished", PropertyInfo(Variant::INT, "status")));
ADD_SIGNAL(MethodInfo("updated", PropertyInfo(Variant::INT, "status"))); ADD_SIGNAL(MethodInfo("updated", PropertyInfo(Variant::INT, "status")));
#ifdef DEBUG_ENABLED #ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("_set_monitor_performance", "enable"), &BTPlayer::_set_monitor_performance); ADD_SIGNAL(MethodInfo("behavior_tree_finished", PropertyInfo(Variant::INT, "status")));
ClassDB::bind_method(D_METHOD("_get_monitor_performance"), &BTPlayer::_get_monitor_performance); #endif
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitor_performance"), "_set_monitor_performance", "_get_monitor_performance");
#endif // DEBUG_ENABLED
} }
BTPlayer::BTPlayer() { BTPlayer::BTPlayer() {

View File

@ -15,6 +15,7 @@
#include "../blackboard/blackboard.h" #include "../blackboard/blackboard.h"
#include "../blackboard/blackboard_plan.h" #include "../blackboard/blackboard_plan.h"
#include "behavior_tree.h" #include "behavior_tree.h"
#include "bt_instance.h"
#include "tasks/bt_task.h" #include "tasks/bt_task.h"
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
@ -42,18 +43,24 @@ private:
UpdateMode update_mode = UpdateMode::PHYSICS; UpdateMode update_mode = UpdateMode::PHYSICS;
bool active = true; bool active = true;
Ref<Blackboard> blackboard; Ref<Blackboard> blackboard;
int last_status = -1; Node *scene_root_hint = nullptr;
bool monitor_performance = false;
Ref<BTTask> tree_instance; Ref<BTInstance> bt_instance;
void _load_tree(); void _load_tree();
void _update_blackboard_plan(); void _update_blackboard_plan();
_FORCE_INLINE_ Node *_get_scene_root() const { return scene_root_hint ? scene_root_hint : get_owner(); }
protected: protected:
static void _bind_methods(); static void _bind_methods();
void _notification(int p_notification); void _notification(int p_notification);
#ifdef LIMBOAI_GDEXTENSION
String _to_string() const { return String(get_name()) + ":<" + get_class() + "#" + itos(get_instance_id()) + ">"; }
#endif
public: 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; };
@ -73,32 +80,19 @@ public:
Ref<Blackboard> get_blackboard() const { return blackboard; } Ref<Blackboard> get_blackboard() const { return blackboard; }
void set_blackboard(const Ref<Blackboard> &p_blackboard) { blackboard = p_blackboard; } void set_blackboard(const Ref<Blackboard> &p_blackboard) { blackboard = p_blackboard; }
void set_monitor_performance(bool p_monitor_performance);
bool get_monitor_performance() const { return monitor_performance; }
void update(double p_delta); void update(double p_delta);
void restart(); void restart();
int get_last_status() const { return last_status; }
Ref<BTTask> get_tree_instance() { return tree_instance; } Ref<BTInstance> get_bt_instance() { return bt_instance; }
void set_bt_instance(const Ref<BTInstance> &p_bt_instance);
void set_scene_root_hint(Node *p_scene_root);
BTPlayer(); BTPlayer();
~BTPlayer(); ~BTPlayer();
#ifdef DEBUG_ENABLED // Performance monitoring
private:
bool monitor_performance = false;
StringName monitor_id;
double update_time_acc = 0.0;
double update_time_n = 0.0;
void _set_monitor_performance(bool p_monitor_performance);
bool _get_monitor_performance() const { return monitor_performance; }
void _add_custom_monitor();
void _remove_custom_monitor();
double _get_mean_update_time_msec();
#endif // DEBUG_ENABLED
}; };
#endif // BT_PLAYER_H #endif // BT_PLAYER_H

View File

@ -11,7 +11,6 @@
#include "bt_state.h" #include "bt_state.h"
#include "../editor/debugger/limbo_debugger.h"
#include "../util/limbo_compat.h" #include "../util/limbo_compat.h"
#include "../util/limbo_string_names.h" #include "../util/limbo_string_names.h"
@ -38,6 +37,23 @@ void BTState::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
_update_blackboard_plan(); _update_blackboard_plan();
} }
void BTState::set_scene_root_hint(Node *p_scene_root) {
ERR_FAIL_NULL_MSG(p_scene_root, "BTState: Failed to set scene root hint - scene root is null.");
ERR_FAIL_COND_MSG(bt_instance.is_valid(), "BTState: Scene root hint shouldn't be set after initialization. This change will not affect the current behavior tree instance.");
scene_root_hint = p_scene_root;
}
void BTState::set_monitor_performance(bool p_monitor) {
monitor_performance = p_monitor;
#ifdef DEBUG_ENABLED
if (bt_instance.is_valid()) {
bt_instance->set_monitor_performance(monitor_performance);
}
#endif
}
void BTState::_update_blackboard_plan() { void BTState::_update_blackboard_plan() {
if (get_blackboard_plan().is_null()) { if (get_blackboard_plan().is_null()) {
set_blackboard_plan(memnew(BlackboardPlan)); set_blackboard_plan(memnew(BlackboardPlan));
@ -49,23 +65,27 @@ void BTState::_update_blackboard_plan() {
} }
} }
Node *BTState::_get_prefetch_root_for_base_plan() {
return _get_scene_root();
}
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.");
Node *scene_root = get_owner(); Node *scene_root = _get_scene_root();
ERR_FAIL_NULL_MSG(scene_root, "BTState: Initialization failed - can't get scene root (make sure the BTState's owner property is set)."); ERR_FAIL_NULL_MSG(scene_root, "BTState: Initialization failed - unable to establish scene root. This is likely due to BTState not being owned by a scene node. Check BTState.set_scene_root_hint().");
tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard(), scene_root); bt_instance = behavior_tree->instantiate(get_agent(), get_blackboard(), this, scene_root);
ERR_FAIL_COND_MSG(bt_instance.is_null(), "BTState: Initialization failed - failed to instantiate behavior tree.");
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) { bt_instance->register_with_debugger();
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path()); bt_instance->set_monitor_performance(monitor_performance);
}
#endif #endif
} }
void BTState::_exit() { void BTState::_exit() {
if (tree_instance.is_valid()) { if (bt_instance.is_valid()) {
tree_instance->abort(); bt_instance->get_root_task()->abort();
} else { } else {
ERR_PRINT_ONCE("BTState: BehaviorTree is not assigned."); ERR_PRINT_ONCE("BTState: BehaviorTree is not assigned.");
} }
@ -78,8 +98,8 @@ void BTState::_update(double p_delta) {
// Bail out if a transition happened in the meantime. // Bail out if a transition happened in the meantime.
return; return;
} }
ERR_FAIL_NULL(tree_instance); ERR_FAIL_NULL(bt_instance);
int status = tree_instance->execute(p_delta); BT::Status status = bt_instance->update(p_delta);
if (status == BTTask::SUCCESS) { if (status == BTTask::SUCCESS) {
get_root()->dispatch(success_event, Variant()); get_root()->dispatch(success_event, Variant());
} else if (status == BTTask::FAILURE) { } else if (status == BTTask::FAILURE) {
@ -92,16 +112,19 @@ void BTState::_notification(int p_notification) {
switch (p_notification) { switch (p_notification) {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) { if (bt_instance.is_valid()) {
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path()); bt_instance->register_with_debugger();
bt_instance->set_monitor_performance(monitor_performance);
} }
} break; } break;
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) { if (bt_instance.is_valid()) {
LimboDebugger::get_singleton()->unregister_bt_instance(tree_instance, get_path()); bt_instance->unregister_with_debugger();
bt_instance->set_monitor_performance(false);
} }
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint()) { if (Engine::get_singleton()->is_editor_hint()) {
@ -117,7 +140,7 @@ void BTState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_behavior_tree", "behavior_tree"), &BTState::set_behavior_tree); ClassDB::bind_method(D_METHOD("set_behavior_tree", "behavior_tree"), &BTState::set_behavior_tree);
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTState::get_behavior_tree); ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTState::get_behavior_tree);
ClassDB::bind_method(D_METHOD("get_tree_instance"), &BTState::get_tree_instance); ClassDB::bind_method(D_METHOD("get_bt_instance"), &BTState::get_bt_instance);
ClassDB::bind_method(D_METHOD("set_success_event", "event"), &BTState::set_success_event); ClassDB::bind_method(D_METHOD("set_success_event", "event"), &BTState::set_success_event);
ClassDB::bind_method(D_METHOD("get_success_event"), &BTState::get_success_event); ClassDB::bind_method(D_METHOD("get_success_event"), &BTState::get_success_event);
@ -125,9 +148,15 @@ void BTState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_failure_event", "event"), &BTState::set_failure_event); ClassDB::bind_method(D_METHOD("set_failure_event", "event"), &BTState::set_failure_event);
ClassDB::bind_method(D_METHOD("get_failure_event"), &BTState::get_failure_event); ClassDB::bind_method(D_METHOD("get_failure_event"), &BTState::get_failure_event);
ClassDB::bind_method(D_METHOD("set_monitor_performance", "enable"), &BTState::set_monitor_performance);
ClassDB::bind_method(D_METHOD("get_monitor_performance"), &BTState::get_monitor_performance);
ClassDB::bind_method(D_METHOD("set_scene_root_hint", "scene_root"), &BTState::set_scene_root_hint);
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::STRING_NAME, "success_event"), "set_success_event", "get_success_event"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "success_event"), "set_success_event", "get_success_event");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "failure_event"), "set_failure_event", "get_failure_event"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "failure_event"), "set_failure_event", "get_failure_event");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitor_performance"), "set_monitor_performance", "get_monitor_performance");
} }
BTState::BTState() { BTState::BTState() {

View File

@ -22,9 +22,13 @@ class BTState : public LimboState {
private: private:
Ref<BehaviorTree> behavior_tree; Ref<BehaviorTree> behavior_tree;
Ref<BTTask> tree_instance; Ref<BTInstance> bt_instance;
StringName success_event; StringName success_event;
StringName failure_event; StringName failure_event;
Node *scene_root_hint = nullptr;
bool monitor_performance = false;
_FORCE_INLINE_ Node *_get_scene_root() const { return scene_root_hint ? scene_root_hint : get_owner(); }
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -33,6 +37,7 @@ protected:
virtual bool _should_use_new_scope() const override { return true; } virtual bool _should_use_new_scope() const override { return true; }
virtual void _update_blackboard_plan() override; virtual void _update_blackboard_plan() override;
virtual Node *_get_prefetch_root_for_base_plan() override;
virtual void _setup() override; virtual void _setup() override;
virtual void _exit() override; virtual void _exit() override;
@ -42,7 +47,7 @@ public:
void set_behavior_tree(const Ref<BehaviorTree> &p_value); void set_behavior_tree(const Ref<BehaviorTree> &p_value);
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; } Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; }
Ref<BTTask> get_tree_instance() const { return tree_instance; } Ref<BTInstance> get_bt_instance() const { return bt_instance; }
void set_success_event(const StringName &p_success_event) { success_event = p_success_event; } void set_success_event(const StringName &p_success_event) { success_event = p_success_event; }
StringName get_success_event() const { return success_event; } StringName get_success_event() const { return success_event; }
@ -50,6 +55,11 @@ public:
void set_failure_event(const StringName &p_failure_event) { failure_event = p_failure_event; } void set_failure_event(const StringName &p_failure_event) { failure_event = p_failure_event; }
StringName get_failure_event() const { return failure_event; } StringName get_failure_event() const { return failure_event; }
void set_monitor_performance(bool p_monitor);
bool get_monitor_performance() const { return monitor_performance; }
void set_scene_root_hint(Node *p_node);
BTState(); BTState();
}; };

View File

@ -24,8 +24,9 @@ void BTCheckVar::set_check_type(LimboUtility::CheckType p_check_type) {
void BTCheckVar::set_value(const Ref<BBVariant> &p_value) { void BTCheckVar::set_value(const Ref<BBVariant> &p_value) {
value = p_value; value = p_value;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && value.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && value.is_valid() &&
value->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !value->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
value->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -48,8 +48,9 @@ void BTSetVar::set_variable(const StringName &p_variable) {
void BTSetVar::set_value(const Ref<BBVariant> &p_value) { void BTSetVar::set_value(const Ref<BBVariant> &p_value) {
value = p_value; value = p_value;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && value.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && value.is_valid() &&
value->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !value->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
value->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -125,6 +125,7 @@ String BTTask::get_task_name() {
Ref<Script> task_script = get_script(); Ref<Script> task_script = get_script();
if (task_script.is_valid()) { if (task_script.is_valid()) {
// ! CURSED: Currently, has_method() doesn't return true for ClassDB-registered native virtual methods. This may break in the future.
bool has_generate_method = has_method(LW_NAME(_generate_name)); 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())); 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) { if (task_script->is_tool() && has_generate_method) {
@ -386,16 +387,21 @@ void BTTask::print_tree(int p_initial_tabs) {
} }
} }
#ifdef TOOLS_ENABLED
Ref<BehaviorTree> BTTask::editor_get_behavior_tree() { Ref<BehaviorTree> BTTask::editor_get_behavior_tree() {
#ifdef TOOLS_ENABLED
BTTask *task = this; BTTask *task = this;
while (task->data.behavior_tree_id.is_null() && task->get_parent().is_valid()) { while (task->data.behavior_tree_id.is_null() && task->get_parent().is_valid()) {
task = task->data.parent; task = task->data.parent;
} }
return Object::cast_to<BehaviorTree>(ObjectDB::get_instance(task->data.behavior_tree_id)); return Object::cast_to<BehaviorTree>(ObjectDB::get_instance(task->data.behavior_tree_id));
#else
ERR_PRINT("BTTask::editor_get_behavior_tree: Not available in release builds.");
return Ref<BehaviorTree>();
#endif
} }
#ifdef TOOLS_ENABLED
void BTTask::editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt) { void BTTask::editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt) {
data.behavior_tree_id = p_bt->get_instance_id(); data.behavior_tree_id = p_bt->get_instance_id();
} }
@ -423,9 +429,7 @@ 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); 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);

View File

@ -111,6 +111,10 @@ protected:
GDVIRTUAL1R(Status, _tick, double); GDVIRTUAL1R(Status, _tick, double);
GDVIRTUAL0RC(PackedStringArray, _get_configuration_warnings); GDVIRTUAL0RC(PackedStringArray, _get_configuration_warnings);
#ifdef LIMBOAI_GDEXTENSION
String _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }
#endif
public: public:
// TODO: GDExtension doesn't have this method hmm... // TODO: GDExtension doesn't have this method hmm...
@ -166,8 +170,8 @@ 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(); Ref<BehaviorTree> editor_get_behavior_tree();
#ifdef TOOLS_ENABLED
void editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt); void editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt);
#endif #endif

View File

@ -43,12 +43,15 @@ void BTForEach::_enter() {
} }
BT::Status BTForEach::_tick(double p_delta) { BT::Status BTForEach::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "ForEach decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BTForEach: Decorator has no child.");
ERR_FAIL_COND_V_MSG(save_var == StringName(), FAILURE, "ForEach save variable is not set."); ERR_FAIL_COND_V_MSG(save_var == StringName(), FAILURE, "BTForEach: Save variable is not set.");
ERR_FAIL_COND_V_MSG(array_var == StringName(), FAILURE, "ForEach array variable is not set."); ERR_FAIL_COND_V_MSG(array_var == StringName(), FAILURE, "BTForEach: Array variable is not set.");
Array arr = get_blackboard()->get_var(array_var, Variant()); Array arr = get_blackboard()->get_var(array_var, Variant());
if (arr.size() == 0) { if (current_idx >= arr.size()) {
if (current_idx != 0) {
WARN_PRINT("BTForEach: Array size changed during iteration.");
}
return SUCCESS; return SUCCESS;
} }
Variant elem = arr[current_idx]; Variant elem = arr[current_idx];

View File

@ -16,8 +16,9 @@
void BTAwaitAnimation::set_animation_player(Ref<BBNode> p_animation_player) { void BTAwaitAnimation::set_animation_player(Ref<BBNode> p_animation_player) {
animation_player_param = p_animation_player; animation_player_param = p_animation_player;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid() &&
animation_player_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !animation_player_param->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
animation_player_param->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -24,8 +24,9 @@ void BTCheckAgentProperty::set_check_type(LimboUtility::CheckType p_check_type)
void BTCheckAgentProperty::set_value(Ref<BBVariant> p_value) { void BTCheckAgentProperty::set_value(Ref<BBVariant> p_value) {
value = p_value; value = p_value;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && value.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && value.is_valid() &&
value->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !value->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
value->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -16,8 +16,9 @@
void BTPauseAnimation::set_animation_player(Ref<BBNode> p_animation_player) { void BTPauseAnimation::set_animation_player(Ref<BBNode> p_animation_player) {
animation_player_param = p_animation_player; animation_player_param = p_animation_player;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid() &&
animation_player_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !animation_player_param->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
animation_player_param->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -16,8 +16,9 @@
void BTPlayAnimation::set_animation_player(Ref<BBNode> p_animation_player) { void BTPlayAnimation::set_animation_player(Ref<BBNode> p_animation_player) {
animation_player_param = p_animation_player; animation_player_param = p_animation_player;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid() &&
animation_player_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !animation_player_param->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
animation_player_param->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -19,8 +19,9 @@ void BTSetAgentProperty::set_property(StringName p_prop) {
void BTSetAgentProperty::set_value(Ref<BBVariant> p_value) { void BTSetAgentProperty::set_value(Ref<BBVariant> p_value) {
value = p_value; value = p_value;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && value.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && value.is_valid() &&
value->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !value->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
value->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }
@ -45,7 +46,9 @@ String BTSetAgentProperty::_generate_name() {
return "SetAgentProperty ???"; return "SetAgentProperty ???";
} }
return vformat("Set agent.%s = %s", property, return vformat("Set agent.%s %s= %s",
property,
LimboUtility::get_singleton()->get_operation_string(operation),
value.is_valid() ? Variant(value) : Variant("???")); value.is_valid() ? Variant(value) : Variant("???"));
} }

View File

@ -16,8 +16,9 @@
void BTStopAnimation::set_animation_player(Ref<BBNode> p_animation_player) { void BTStopAnimation::set_animation_player(Ref<BBNode> p_animation_player) {
animation_player_param = p_animation_player; animation_player_param = p_animation_player;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid() &&
animation_player_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !animation_player_param->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
animation_player_param->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -28,8 +28,9 @@ void BTCallMethod::set_method(const StringName &p_method_name) {
void BTCallMethod::set_node_param(const Ref<BBNode> &p_object) { void BTCallMethod::set_node_param(const Ref<BBNode> &p_object) {
node_param = p_object; node_param = p_object;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && node_param.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && node_param.is_valid() &&
node_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !node_param->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
node_param->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -29,8 +29,9 @@ void BTEvaluateExpression::set_expression_string(const String &p_expression_stri
void BTEvaluateExpression::set_node_param(Ref<BBNode> p_object) { void BTEvaluateExpression::set_node_param(Ref<BBNode> p_object) {
node_param = p_object; node_param = p_object;
emit_changed(); emit_changed();
if (Engine::get_singleton()->is_editor_hint() && node_param.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && node_param.is_valid() &&
node_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed))); !node_param->is_connected(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed))) {
node_param->connect(LW_NAME(changed), callable_mp((Resource *)this, &Resource::emit_changed));
} }
} }

View File

@ -83,6 +83,7 @@ def get_doc_classes():
"BTDynamicSequence", "BTDynamicSequence",
"BTFail", "BTFail",
"BTForEach", "BTForEach",
"BTInstance",
"BTInvert", "BTInvert",
"BTNewScope", "BTNewScope",
"BTParallel", "BTParallel",

View File

@ -41,6 +41,8 @@ func _physics_process(delta: float) -> void:
func _die() -> void: func _die() -> void:
if _is_dead:
return
_is_dead = true _is_dead = true
trail.emitting = false trail.emitting = false
root.hide() root.hide()

View File

@ -39,6 +39,8 @@ func _physics_process(delta: float) -> void:
func _die() -> void: func _die() -> void:
if _is_dead:
return
_is_dead = true _is_dead = true
root.hide() root.hide()
collision_shape_2d.set_deferred(&"disabled", true) collision_shape_2d.set_deferred(&"disabled", true)

View File

@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/junction_bold.otf-4db2200a8b1a6423bafe2a4e7c7
Rendering=null Rendering=null
antialiasing=1 antialiasing=1
generate_mipmaps=false generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false multichannel_signed_distance_field=false
msdf_pixel_range=8 msdf_pixel_range=8
msdf_size=48 msdf_size=48

View File

@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/knewave_regular.ttf-955953b059f713782c7b07e66
Rendering=null Rendering=null
antialiasing=1 antialiasing=1
generate_mipmaps=false generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false multichannel_signed_distance_field=false
msdf_pixel_range=8 msdf_pixel_range=8
msdf_size=48 msdf_size=48

View File

@ -42,8 +42,8 @@ func _ready() -> void:
func _physics_process(_delta: float) -> void: func _physics_process(_delta: float) -> void:
var inst: BTTask = bt_player.get_tree_instance() var inst: BTInstance = bt_player.get_bt_instance()
var bt_data: BehaviorTreeData = BehaviorTreeData.create_from_tree_instance(inst) var bt_data: BehaviorTreeData = BehaviorTreeData.create_from_bt_instance(inst)
behavior_tree_view.update_tree(bt_data) behavior_tree_view.update_tree(bt_data)

View File

@ -234,18 +234,18 @@ unique_name_in_owner = true
custom_minimum_size = Vector2(0, 140) custom_minimum_size = Vector2(0, 140)
layout_mode = 2 layout_mode = 2
size_flags_vertical = 3 size_flags_vertical = 3
theme_override_font_sizes/bold_italics_font_size = 20
theme_override_font_sizes/italics_font_size = 20
theme_override_font_sizes/mono_font_size = 20
theme_override_font_sizes/normal_font_size = 20 theme_override_font_sizes/normal_font_size = 20
theme_override_font_sizes/bold_font_size = 20 theme_override_font_sizes/bold_font_size = 20
theme_override_font_sizes/italics_font_size = 20
theme_override_font_sizes/bold_italics_font_size = 20
theme_override_font_sizes/mono_font_size = 20
bbcode_enabled = true bbcode_enabled = true
text = "[b]Behavior Trees[/b] are composed of tasks that represent specific actions or decision-making rules. Tasks can be broadly categorized into two main types: control tasks and leaf tasks. Control tasks determine the execution flow within the tree. They include Sequence, Selector, and Invert. Leaf tasks represent specific actions to perform, like moving or attacking, or conditions that need to be checked. The BTTask class provides the foundation for various building blocks of the Behavior Trees. BT tasks can share data with the help of the Blackboard." text = "[b]Behavior Trees[/b] are composed of tasks that represent specific actions or decision-making rules. Tasks can be broadly categorized into two main types: control tasks and leaf tasks. Control tasks determine the execution flow within the tree. They include Sequence, Selector, and Invert. Leaf tasks represent specific actions to perform, like moving or attacking, or conditions that need to be checked. The BTTask class provides the foundation for various building blocks of the Behavior Trees. BT tasks can share data with the help of the Blackboard."
fit_content = true fit_content = true
[node name="CodePopup" type="PopupPanel" parent="UI Layer/Control"] [node name="CodePopup" type="PopupPanel" parent="UI Layer/Control"]
unique_name_in_owner = true unique_name_in_owner = true
position = Vector2i(135, 60) position = Vector2i(0, 60)
size = Vector2i(1024, 708) size = Vector2i(1024, 708)
visible = true visible = true
@ -257,8 +257,8 @@ anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = 4.0 offset_left = 4.0
offset_top = 4.0 offset_top = 4.0
offset_right = -4.0 offset_right = 1020.0
offset_bottom = -4.0 offset_bottom = 704.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
gutters_draw_line_numbers = true gutters_draw_line_numbers = true

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBAabb.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBAabb.xml.
.. _class_BBAabb: .. _class_BBAabb:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBArray.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBArray.xml.
.. _class_BBArray: .. _class_BBArray:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBBasis.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBBasis.xml.
.. _class_BBBasis: .. _class_BBBasis:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBBool.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBBool.xml.
.. _class_BBBool: .. _class_BBBool:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBByteArray.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBByteArray.xml.
.. _class_BBByteArray: .. _class_BBByteArray:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBColor.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBColor.xml.
.. _class_BBColor: .. _class_BBColor:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBColorArray.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBColorArray.xml.
.. _class_BBColorArray: .. _class_BBColorArray:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBDictionary.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBDictionary.xml.
.. _class_BBDictionary: .. _class_BBDictionary:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBFloat.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBFloat.xml.
.. _class_BBFloat: .. _class_BBFloat:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBFloat32Array.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBFloat32Array.xml.
.. _class_BBFloat32Array: .. _class_BBFloat32Array:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBFloat64Array.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBFloat64Array.xml.
.. _class_BBFloat64Array: .. _class_BBFloat64Array:

View File

@ -1,23 +0,0 @@
:github_url: hide
.. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/4.2/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/4.2/modules/limboai/doc_classes/BBFloatArray.xml.
.. _class_BBFloatArray:
BBFloatArray
============
**Inherits:** :ref:`BBParam<class_BBParam>`
FloatArray-type parameter for :ref:`BehaviorTree<class_BehaviorTree>` tasks. See :ref:`BBParam<class_BBParam>`.
.. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)`
.. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)`
.. |vararg| replace:: :abbr:`vararg (This method accepts any number of arguments after the ones described here.)`
.. |constructor| replace:: :abbr:`constructor (This method is used to construct a type.)`
.. |static| replace:: :abbr:`static (This method doesn't need an instance to be called, so it can be called directly using the class name.)`
.. |operator| replace:: :abbr:`operator (This method describes a valid operator to use with this type as left-hand operand.)`
.. |bitfield| replace:: :abbr:`BitField (This value is an integer composed as a bitmask of the following flags.)`

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBInt.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBInt.xml.
.. _class_BBInt: .. _class_BBInt:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBInt32Array.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBInt32Array.xml.
.. _class_BBInt32Array: .. _class_BBInt32Array:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBInt64Array.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBInt64Array.xml.
.. _class_BBInt64Array: .. _class_BBInt64Array:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBNode.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBNode.xml.
.. _class_BBNode: .. _class_BBNode:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBParam.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBParam.xml.
.. _class_BBParam: .. _class_BBParam:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBPlane.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBPlane.xml.
.. _class_BBPlane: .. _class_BBPlane:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBProjection.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBProjection.xml.
.. _class_BBProjection: .. _class_BBProjection:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBQuaternion.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBQuaternion.xml.
.. _class_BBQuaternion: .. _class_BBQuaternion:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBRect2.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBRect2.xml.
.. _class_BBRect2: .. _class_BBRect2:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBRect2i.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBRect2i.xml.
.. _class_BBRect2i: .. _class_BBRect2i:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBString.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBString.xml.
.. _class_BBString: .. _class_BBString:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBStringArray.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBStringArray.xml.
.. _class_BBStringArray: .. _class_BBStringArray:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBStringName.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBStringName.xml.
.. _class_BBStringName: .. _class_BBStringName:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBTransform2D.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBTransform2D.xml.
.. _class_BBTransform2D: .. _class_BBTransform2D:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBTransform3D.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBTransform3D.xml.
.. _class_BBTransform3D: .. _class_BBTransform3D:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVariant.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVariant.xml.
.. _class_BBVariant: .. _class_BBVariant:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector2.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector2.xml.
.. _class_BBVector2: .. _class_BBVector2:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector2Array.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector2Array.xml.
.. _class_BBVector2Array: .. _class_BBVector2Array:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector2i.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector2i.xml.
.. _class_BBVector2i: .. _class_BBVector2i:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector3.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector3.xml.
.. _class_BBVector3: .. _class_BBVector3:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector3Array.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector3Array.xml.
.. _class_BBVector3Array: .. _class_BBVector3Array:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector3i.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector3i.xml.
.. _class_BBVector3i: .. _class_BBVector3i:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector4.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector4.xml.
.. _class_BBVector4: .. _class_BBVector4:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BBVector4i.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BBVector4i.xml.
.. _class_BBVector4i: .. _class_BBVector4i:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BehaviorTree.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BehaviorTree.xml.
.. _class_BehaviorTree: .. _class_BehaviorTree:
@ -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>`\ (\ other\: :ref:`BehaviorTree<class_BehaviorTree>`\ ) | | |void| | :ref:`copy_other<class_BehaviorTree_method_copy_other>`\ (\ other\: :ref:`BehaviorTree<class_BehaviorTree>`\ ) |
+-----------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| :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>`\ (\ agent\: ``Node``, blackboard\: :ref:`Blackboard<class_Blackboard>`, scene_root\: ``Node``\ ) |const| | | :ref:`BTInstance<class_BTInstance>` | :ref:`instantiate<class_BehaviorTree_method_instantiate>`\ (\ agent\: ``Node``, blackboard\: :ref:`Blackboard<class_Blackboard>`, instance_owner\: ``Node``, custom_scene_root\: ``Node`` = null\ ) |const| |
+-----------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |void| | :ref:`set_root_task<class_BehaviorTree_method_set_root_task>`\ (\ task\: :ref:`BTTask<class_BTTask>`\ ) | | |void| | :ref:`set_root_task<class_BehaviorTree_method_set_root_task>`\ (\ task\: :ref:`BTTask<class_BTTask>`\ ) |
+-----------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
.. rst-class:: classref-section-separator .. rst-class:: classref-section-separator
@ -121,7 +121,7 @@ Stores and manages variables that will be used in constructing new :ref:`Blackbo
- |void| **set_description**\ (\ value\: ``String``\ ) - |void| **set_description**\ (\ value\: ``String``\ )
- ``String`` **get_description**\ (\ ) - ``String`` **get_description**\ (\ )
User-provided description of the BehaviorTree. User-provided description of the **BehaviorTree**.
.. rst-class:: classref-section-separator .. rst-class:: classref-section-separator
@ -172,9 +172,11 @@ Returns the root task of the BehaviorTree resource.
.. rst-class:: classref-method .. rst-class:: classref-method
:ref:`BTTask<class_BTTask>` **instantiate**\ (\ agent\: ``Node``, blackboard\: :ref:`Blackboard<class_Blackboard>`, scene_root\: ``Node``\ ) |const| :ref:`🔗<class_BehaviorTree_method_instantiate>` :ref:`BTInstance<class_BTInstance>` **instantiate**\ (\ agent\: ``Node``, blackboard\: :ref:`Blackboard<class_Blackboard>`, instance_owner\: ``Node``, custom_scene_root\: ``Node`` = null\ ) |const| :ref:`🔗<class_BehaviorTree_method_instantiate>`
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). Instantiates the behavior tree and returns :ref:`BTInstance<class_BTInstance>`. ``instance_owner`` should be the scene node that will own the behavior tree instance. This is typically a :ref:`BTPlayer<class_BTPlayer>`, :ref:`BTState<class_BTState>`, or a custom player node that controls the behavior tree execution. Make sure to pass a :ref:`Blackboard<class_Blackboard>` with values populated from :ref:`blackboard_plan<class_BehaviorTree_property_blackboard_plan>`. See also :ref:`BlackboardPlan.populate_blackboard<class_BlackboardPlan_method_populate_blackboard>` & :ref:`BlackboardPlan.create_blackboard<class_BlackboardPlan_method_create_blackboard>`.
If ``custom_scene_root`` is not ``null``, it will be used as the scene root for the newly instantiated behavior tree; otherwise, the scene root will be set to ``instance_owner.owner``. Scene root is essential for :ref:`BBNode<class_BBNode>` instances to work properly.
.. rst-class:: classref-item-separator .. rst-class:: classref-item-separator

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BehaviorTreeData.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BehaviorTreeData.xml.
.. _class_BehaviorTreeData: .. _class_BehaviorTreeData:
@ -31,9 +31,9 @@ Methods
.. table:: .. table::
:widths: auto :widths: auto
+-------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| :ref:`BehaviorTreeData<class_BehaviorTreeData>` | :ref:`create_from_tree_instance<class_BehaviorTreeData_method_create_from_tree_instance>`\ (\ tree_instance\: :ref:`BTTask<class_BTTask>`\ ) |static| | | :ref:`BehaviorTreeData<class_BehaviorTreeData>` | :ref:`create_from_bt_instance<class_BehaviorTreeData_method_create_from_bt_instance>`\ (\ bt_instance\: :ref:`BTInstance<class_BTInstance>`\ ) |static| |
+-------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
.. rst-class:: classref-section-separator .. rst-class:: classref-section-separator
@ -44,15 +44,15 @@ Methods
Method Descriptions Method Descriptions
------------------- -------------------
.. _class_BehaviorTreeData_method_create_from_tree_instance: .. _class_BehaviorTreeData_method_create_from_bt_instance:
.. rst-class:: classref-method .. rst-class:: classref-method
:ref:`BehaviorTreeData<class_BehaviorTreeData>` **create_from_tree_instance**\ (\ tree_instance\: :ref:`BTTask<class_BTTask>`\ ) |static| :ref:`🔗<class_BehaviorTreeData_method_create_from_tree_instance>` :ref:`BehaviorTreeData<class_BehaviorTreeData>` **create_from_bt_instance**\ (\ bt_instance\: :ref:`BTInstance<class_BTInstance>`\ ) |static| :ref:`🔗<class_BehaviorTreeData_method_create_from_bt_instance>`
Returns current state of the ``tree_instance`` encoded as a **BehaviorTreeData**, suitable for use with :ref:`BehaviorTreeView<class_BehaviorTreeView>`. Returns current state of the ``bt_instance`` encoded as a **BehaviorTreeData**, suitable for use with :ref:`BehaviorTreeView<class_BehaviorTreeView>`.
Behavior tree instance can be acquired with :ref:`BTPlayer.get_tree_instance<class_BTPlayer_method_get_tree_instance>`. Behavior tree instance can be acquired with :ref:`BTPlayer.get_bt_instance<class_BTPlayer_method_get_bt_instance>`.
.. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)` .. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)`
.. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)` .. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)`

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BehaviorTreeView.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BehaviorTreeView.xml.
.. _class_BehaviorTreeView: .. _class_BehaviorTreeView:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/Blackboard.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/Blackboard.xml.
.. _class_Blackboard: .. _class_Blackboard:
@ -126,7 +126,7 @@ Returns a Blackboard that serves as the parent scope for this instance.
``Variant`` **get_var**\ (\ var_name\: ``StringName``, default\: ``Variant`` = null, complain\: ``bool`` = true\ ) |const| :ref:`🔗<class_Blackboard_method_get_var>` ``Variant`` **get_var**\ (\ var_name\: ``StringName``, default\: ``Variant`` = null, complain\: ``bool`` = true\ ) |const| :ref:`🔗<class_Blackboard_method_get_var>`
Returns variable value or ``default`` if variable doesn't exist. If ``complain`` is ``true``, an error will be printed if variable doesn't exist. Returns variable value or ``default`` if variable doesn't exist. If ``complain`` is ``true``, an error will be printed if variable doesn't exist. If the variable doesn't exist in the current **Blackboard** scope, it will look in the parent scope **Blackboard** to find it.
.. rst-class:: classref-item-separator .. rst-class:: classref-item-separator
@ -212,7 +212,7 @@ Assigns the parent scope. If a value isn't in the current Blackboard scope, it w
|void| **set_var**\ (\ var_name\: ``StringName``, value\: ``Variant``\ ) :ref:`🔗<class_Blackboard_method_set_var>` |void| **set_var**\ (\ var_name\: ``StringName``, value\: ``Variant``\ ) :ref:`🔗<class_Blackboard_method_set_var>`
Assigns a value to a Blackboard variable. Assigns a value to a variable in the current Blackboard scope. If the variable doesn't exist, it will be created. If the variable already exists in the parent scope, the parent scope value will NOT be changed.
.. rst-class:: classref-item-separator .. rst-class:: classref-item-separator

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BlackboardPlan.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BlackboardPlan.xml.
.. _class_BlackboardPlan: .. _class_BlackboardPlan:
@ -34,23 +34,23 @@ Methods
.. table:: .. table::
:widths: auto :widths: auto
+---------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| :ref:`Blackboard<class_Blackboard>` | :ref:`create_blackboard<class_BlackboardPlan_method_create_blackboard>`\ (\ node\: ``Node``, parent_scope\: :ref:`Blackboard<class_Blackboard>` = null\ ) | | :ref:`Blackboard<class_Blackboard>` | :ref:`create_blackboard<class_BlackboardPlan_method_create_blackboard>`\ (\ prefetch_root\: ``Node``, parent_scope\: :ref:`Blackboard<class_Blackboard>` = null, prefetch_root_for_base_plan\: ``Node`` = 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| | | ``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>`\ (\ blackboard\: :ref:`Blackboard<class_Blackboard>`, overwrite\: ``bool``, node\: ``Node``\ ) | | |void| | :ref:`populate_blackboard<class_BlackboardPlan_method_populate_blackboard>`\ (\ blackboard\: :ref:`Blackboard<class_Blackboard>`, overwrite\: ``bool``, prefetch_root\: ``Node``, prefetch_root_for_base_plan\: ``Node`` = null\ ) |
+---------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |void| | :ref:`set_base_plan<class_BlackboardPlan_method_set_base_plan>`\ (\ blackboard_plan\: :ref:`BlackboardPlan<class_BlackboardPlan>`\ ) | | |void| | :ref:`set_base_plan<class_BlackboardPlan_method_set_base_plan>`\ (\ blackboard_plan\: :ref:`BlackboardPlan<class_BlackboardPlan>`\ ) |
+---------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |void| | :ref:`set_parent_scope_plan_provider<class_BlackboardPlan_method_set_parent_scope_plan_provider>`\ (\ callable\: ``Callable``\ ) | | |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>`\ (\ ) |
+---------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
.. rst-class:: classref-section-separator .. rst-class:: classref-section-separator
@ -87,9 +87,9 @@ Method Descriptions
.. rst-class:: classref-method .. rst-class:: classref-method
:ref:`Blackboard<class_Blackboard>` **create_blackboard**\ (\ node\: ``Node``, parent_scope\: :ref:`Blackboard<class_Blackboard>` = null\ ) :ref:`🔗<class_BlackboardPlan_method_create_blackboard>` :ref:`Blackboard<class_Blackboard>` **create_blackboard**\ (\ prefetch_root\: ``Node``, parent_scope\: :ref:`Blackboard<class_Blackboard>` = null, prefetch_root_for_base_plan\: ``Node`` = null\ ) :ref:`🔗<class_BlackboardPlan_method_create_blackboard>`
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, ``prefetch_root`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values.
.. rst-class:: classref-item-separator .. rst-class:: classref-item-separator
@ -135,9 +135,9 @@ Returns ``true`` if this plan is derived from another, i.e., the base plan is no
.. rst-class:: classref-method .. rst-class:: classref-method
|void| **populate_blackboard**\ (\ blackboard\: :ref:`Blackboard<class_Blackboard>`, overwrite\: ``bool``, node\: ``Node``\ ) :ref:`🔗<class_BlackboardPlan_method_populate_blackboard>` |void| **populate_blackboard**\ (\ blackboard\: :ref:`Blackboard<class_Blackboard>`, overwrite\: ``bool``, prefetch_root\: ``Node``, prefetch_root_for_base_plan\: ``Node`` = null\ ) :ref:`🔗<class_BlackboardPlan_method_populate_blackboard>`
Populates ``blackboard`` with the variables from this plan. If ``overwrite`` is ``true``, existing variables with the same names will be overwritten. If ``NodePath`` prefetching is enabled, ``node`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values. Populates ``blackboard`` with the variables from this plan. If ``overwrite`` is ``true``, existing variables with the same names will be overwritten. If ``NodePath`` prefetching is enabled, ``prefetch_root`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values.
.. rst-class:: classref-item-separator .. rst-class:: classref-item-separator

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BT.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BT.xml.
.. _class_BT: .. _class_BT:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTAction.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTAction.xml.
.. _class_BTAction: .. _class_BTAction:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTAlwaysFail.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTAlwaysFail.xml.
.. _class_BTAlwaysFail: .. _class_BTAlwaysFail:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTAlwaysSucceed.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTAlwaysSucceed.xml.
.. _class_BTAlwaysSucceed: .. _class_BTAlwaysSucceed:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTAwaitAnimation.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTAwaitAnimation.xml.
.. _class_BTAwaitAnimation: .. _class_BTAwaitAnimation:
@ -95,7 +95,7 @@ Parameter that specifies the ``AnimationPlayer`` node.
- |void| **set_max_time**\ (\ value\: ``float``\ ) - |void| **set_max_time**\ (\ value\: ``float``\ )
- ``float`` **get_max_time**\ (\ ) - ``float`` **get_max_time**\ (\ )
The maximum duration to wait for the animation to complete (in seconds). If the animation doesn't finish within this time, BTAwaitAnimation will return ``FAILURE``. The maximum duration to wait for the animation to complete (in seconds). If the animation doesn't finish within this time, BTAwaitAnimation will stop waiting and return ``SUCCESS``.
.. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)` .. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)`
.. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)` .. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)`

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTCallMethod.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTCallMethod.xml.
.. _class_BTCallMethod: .. _class_BTCallMethod:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTCheckAgentProperty.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTCheckAgentProperty.xml.
.. _class_BTCheckAgentProperty: .. _class_BTCheckAgentProperty:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTCheckTrigger.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTCheckTrigger.xml.
.. _class_BTCheckTrigger: .. _class_BTCheckTrigger:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTCheckVar.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTCheckVar.xml.
.. _class_BTCheckVar: .. _class_BTCheckVar:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTComment.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTComment.xml.
.. _class_BTComment: .. _class_BTComment:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTComposite.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTComposite.xml.
.. _class_BTComposite: .. _class_BTComposite:

View File

@ -2,8 +2,8 @@
.. DO NOT EDIT THIS FILE!!! .. DO NOT EDIT THIS FILE!!!
.. Generated automatically from Godot engine sources. .. Generated automatically from Godot engine sources.
.. Generator: https://github.com/godotengine/godot/tree/master/doc/tools/make_rst.py. .. Generator: https://github.com/godotengine/godot/tree/4.3/doc/tools/make_rst.py.
.. XML source: https://github.com/godotengine/godot/tree/master/modules/limboai/doc_classes/BTCondition.xml. .. XML source: https://github.com/godotengine/godot/tree/4.3/modules/limboai/doc_classes/BTCondition.xml.
.. _class_BTCondition: .. _class_BTCondition:

Some files were not shown because too many files have changed in this diff Show More