Compare commits

...

14 Commits

Author SHA1 Message Date
Wilson E. Alvarez 8a2dac5b6b
Merge 8f684f4169 into e9eec23c3e 2024-05-26 22:22:03 +02:00
Serhii Snitsaruk e9eec23c3e
Update README.md
Put first steps earlier in the README
2024-05-26 12:39:04 +02:00
Serhii Snitsaruk d0fcea5574
Merge pull request #118 from limbonaut/doc-first-steps
Doc: Add first steps
2024-05-26 12:36:42 +02:00
Serhii Snitsaruk e059429760
Doc: Add first steps 2024-05-26 12:34:18 +02:00
Serhii Snitsaruk 918095622c
Merge pull request #117 from limbonaut/gha-toolchain-mirror
GHA: Use godotengine buildroot mirror
2024-05-26 12:16:14 +02:00
Serhii Snitsaruk 23c19c11e6
GHA: Use godotengine buildroot mirror 2024-05-26 09:32:49 +02:00
Wilson E. Alvarez 8f684f4169
Fix List<T> access
Due to upstream change:

	955d5affa8
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez 5258506e12
Fix GCC warning for unhandled 'PACKED_VECTOR4_ARRAY' in switch
Due to upstream change:

	f9b488508c
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez 2f0468bb00
Update EditorPlugin header location
Due to upstream change:

	1bcbbe96c4
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez 2c740e7741
Update EditorHelpBit calls
Due to upstream change:

	a714cb9f65
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez 606b5a9276
Add missing MarginContainer header
Due to upstream change:

	7884d63281
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez fa1fd7f55f
Fix bottom panel visbility calls
Due to upstream change:

	eb6ca91ba6
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez 127696e5ac
Migrate to Tree::set_custom_draw_callback
Due to upstream change:

	a32a2eaedc
2024-05-07 09:41:30 -04:00
Wilson E. Alvarez 5e5f849208
Fix upstream EditorScale header locations
Due to upstream change:

	4b55c81eba
2024-05-07 09:41:30 -04:00
16 changed files with 76 additions and 40 deletions

View File

@ -11,9 +11,9 @@ runs:
shell: bash
run: |
# ! Settings:
TOOLCHAIN_64_URL=https://downloads.tuxfamily.org/godotengine/toolchains/linux/2021-02-11/x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
TOOLCHAIN_64_URL=https://github.com/godotengine/buildroot/releases/download/godot-2020.11.x-2/x86_64-godot-linux-gnu_sdk-buildroot.tar.bz2
TOOLCHAIN_64_SHA=16c8302fcb676c1f0fb9df73d6cff250ba1f4286
TOOLCHAIN_32_URL=https://downloads.tuxfamily.org/godotengine/toolchains/linux/2021-02-11/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
# ! Export variables:
if [[ "${{ inputs.arch }}" == "x86_64" ]]; then

View File

@ -72,6 +72,10 @@ Behavior Trees are powerful hierarchical structures used to model and control th
- **Demo + Tutorial:** Check out our extensive demo project, which includes an introduction to behavior trees using examples.
## First steps
Follow the [First steps](https://limboai.readthedocs.io/en/latest/index.html#first-steps) guide to learn how to get started with LimboAI and the demo project.
## Getting LimboAI
LimboAI can be used as either a C++ module or as a GDExtension shared library. GDExtension version is more convenient to use but somewhat limited in features. Whichever you choose to use, your project will stay compatible with both and you can switch from one to the other any time. See [Using GDExtension](https://limboai.readthedocs.io/en/latest/getting-started/gdextension.html).
@ -93,6 +97,7 @@ LimboAI can be used as either a C++ module or as a GDExtension shared library. G
## Using the plugin
- [Online Documentation](https://limboai.readthedocs.io/en/latest/index.html)
- [First steps](https://limboai.readthedocs.io/en/latest/index.html#first-steps)
- [Introduction to Behavior Trees](https://limboai.readthedocs.io/en/latest/getting-started/introduction.html)
- [Creating custom tasks in GDScript](https://limboai.readthedocs.io/en/latest/getting-started/custom-tasks.html)
- [Sharing data using Blackboard](https://limboai.readthedocs.io/en/latest/getting-started/using-blackboard.html)

View File

@ -237,7 +237,7 @@ BBVariable BlackboardPlan::get_var(const StringName &p_name) {
Pair<StringName, BBVariable> BlackboardPlan::get_var_by_index(int p_index) {
Pair<StringName, BBVariable> ret;
ERR_FAIL_INDEX_V(p_index, (int)var_map.size(), ret);
return var_list[p_index];
return var_list.get(p_index);
}
PackedStringArray BlackboardPlan::list_vars() const {

View File

@ -34,6 +34,44 @@ the other any time. For more information on this topic, see :ref:`gdextension`.
**🛈 Note:** Class reference is available in the side bar.
First steps
-----------
Choose the version you'd like to use. The module version provides better editor
experience and performance, while the GDExtension version is more convenient to use.
If you're unsure, start with the GDExtension version.
You can change your decision at any time - both versions are fully compatible.
For more information, see :ref:`gdextension`.
With GDExtension version
~~~~~~~~~~~~~~~~~~~~~~~~
1. Make sure you're using the latest stable version of the Godot editor.
2. Create a new project for your experiments with LimboAI.
3. In Godot, click AssetLib tab at the top of the screen and search for LimboAI. Download it. LimboAI plugin will be downloaded with the demo project files. Don't mind the errors printed at this point, this is due to the extension library not being loaded just yet.
4. Reload your project with `Project -> Reload project`. There shouldn't be any errors printed now.
5. In the project files, locate a scene file called `showcase.tscn` and run it. It's the demo's entry point.
With module version
~~~~~~~~~~~~~~~~~~~
1. In `GitHub releases <https://github.com/limbonaut/limboai/releases/>`_, download the latest pre-compiled release build for your platform.
2. Download the demo project archive from the same release.
3. Extract the pre-compiled editor and the demo project files.
4. Launch the pre-compiled editor binary, import and open the demo project.
5. Run the project.
Creating your own behavior trees
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Make a scene file for your agent, or open an existing scene.
2. Add a :ref:`BTPlayer<class_BTPlayer>` node to your scene.
3. Select :ref:`BTPlayer<class_BTPlayer>`, and create a new behavior tree in the inspector.
4. Optionally, you can save the behavior tree to a file using the property's context menu.
5. Click the behavior tree property to open it in the LimboAI editor.
.. toctree::
:hidden:
:maxdepth: 1

View File

@ -17,7 +17,7 @@
#include "../util/limbo_string_names.h"
#ifdef LIMBOAI_MODULE
#include "editor/editor_scale.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#endif // LIMBOAI_MODULE

View File

@ -19,8 +19,9 @@
#ifdef LIMBOAI_MODULE
#include "editor/editor_interface.h"
#include "editor/editor_scale.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
#include "scene/resources/style_box_flat.h"
#endif // LIMBOAI_MODULE

View File

@ -26,7 +26,7 @@ Array BehaviorTreeData::serialize(const Ref<BTTask> &p_tree_instance, const Node
List<Ref<BTTask>> stack;
stack.push_back(p_tree_instance);
while (stack.size()) {
Ref<BTTask> task = stack[0];
Ref<BTTask> task = stack.front()->get();
stack.pop_front();
int num_children = task->get_child_count();
@ -87,7 +87,7 @@ Ref<BehaviorTreeData> BehaviorTreeData::create_from_tree_instance(const Ref<BTTa
List<Ref<BTTask>> stack;
stack.push_back(p_tree_instance);
while (stack.size()) {
Ref<BTTask> task = stack[0];
Ref<BTTask> task = stack.front()->get();
stack.pop_front();
int num_children = task->get_child_count();

View File

@ -24,8 +24,8 @@
#include "core/object/callable_method_pointer.h"
#include "core/os/time.h"
#include "core/typedefs.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/themes/editor_scale.h"
#include "scene/resources/style_box.h"
#endif // LIMBOAI_MODULE
@ -111,7 +111,7 @@ void BehaviorTreeView::_update_tree(const Ref<BehaviorTreeData> &p_data) {
selected_id = item_get_task_id(tree->get_selected());
}
if (last_root_id != 0 && p_data->tasks.size() > 0 && last_root_id == (uint64_t)p_data->tasks[0].id) {
if (last_root_id != 0 && p_data->tasks.size() > 0 && last_root_id == (uint64_t)p_data->tasks.front()->get().id) {
// * Update tree.
// ! Update routine is built on assumption that the behavior tree does NOT mutate. With little work it could detect mutations.
@ -120,29 +120,29 @@ void BehaviorTreeView::_update_tree(const Ref<BehaviorTreeData> &p_data) {
while (item) {
ERR_FAIL_COND(idx >= p_data->tasks.size());
const BTTask::Status current_status = (BTTask::Status)p_data->tasks[idx].status;
const BTTask::Status current_status = (BTTask::Status)p_data->tasks.get(idx).status;
const BTTask::Status last_status = item_get_task_status(item);
const bool status_changed = last_status != p_data->tasks[idx].status;
const bool status_changed = last_status != p_data->tasks.get(idx).status;
if (status_changed) {
item->set_metadata(1, current_status);
if (current_status == BTTask::SUCCESS) {
item->set_custom_draw(0, this, LW_NAME(_draw_success_status));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_success_status));
item->set_icon(1, theme_cache.icon_success);
} else if (current_status == BTTask::FAILURE) {
item->set_custom_draw(0, this, LW_NAME(_draw_failure_status));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_failure_status));
item->set_icon(1, theme_cache.icon_failure);
} else if (current_status == BTTask::RUNNING) {
item->set_custom_draw(0, this, LW_NAME(_draw_running_status));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_running_status));
item->set_icon(1, theme_cache.icon_running);
} else {
item->set_custom_draw(0, this, LW_NAME(_draw_fresh));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_fresh));
item->set_icon(1, nullptr);
}
}
if (status_changed || current_status == BTTask::RUNNING) {
_item_set_elapsed_time(item, p_data->tasks[idx].elapsed_time);
_item_set_elapsed_time(item, p_data->tasks.get(idx).elapsed_time);
}
if (item->get_first_child()) {
@ -165,7 +165,7 @@ void BehaviorTreeView::_update_tree(const Ref<BehaviorTreeData> &p_data) {
} else {
// * Create new tree.
last_root_id = p_data->tasks.size() > 0 ? p_data->tasks[0].id : 0;
last_root_id = p_data->tasks.size() > 0 ? p_data->tasks.front()->get().id : 0;
tree->clear();
TreeItem *parent = nullptr;
@ -174,7 +174,7 @@ void BehaviorTreeView::_update_tree(const Ref<BehaviorTreeData> &p_data) {
// Figure out parent.
parent = nullptr;
if (parents.size()) {
Pair<TreeItem *, int> &p = parents[0];
Pair<TreeItem *, int> &p = parents.front()->get();
parent = p.first;
if (!(--p.second)) {
// No children left, remove it.
@ -204,13 +204,13 @@ void BehaviorTreeView::_update_tree(const Ref<BehaviorTreeData> &p_data) {
item->set_icon_max_width(0, 16 * _get_editor_scale()); // Force user icon size.
if (task_data.status == BTTask::SUCCESS) {
item->set_custom_draw(0, this, LW_NAME(_draw_success_status));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_success_status));
item->set_icon(1, theme_cache.icon_success);
} else if (task_data.status == BTTask::FAILURE) {
item->set_custom_draw(0, this, LW_NAME(_draw_failure_status));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_failure_status));
item->set_icon(1, theme_cache.icon_failure);
} else if (task_data.status == BTTask::RUNNING) {
item->set_custom_draw(0, this, LW_NAME(_draw_running_status));
item->set_custom_draw_callback(0, callable_mp(this, &BehaviorTreeView::_draw_running_status));
item->set_icon(1, theme_cache.icon_running);
}

View File

@ -31,9 +31,9 @@
#include "core/variant/array.h"
#include "editor/editor_interface.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/filesystem_dock.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/control.h"
#include "scene/gui/item_list.h"

View File

@ -34,12 +34,13 @@
#include "editor/editor_file_system.h"
#include "editor/editor_help.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_bottom_panel.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/project_settings_editor.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/separator.h"
#endif // LIMBOAI_MODULE
@ -682,7 +683,7 @@ void LimboAIEditor::_misc_option_selected(int p_id) {
LimboDebuggerPlugin::get_singleton()->get_first_session_window()->set_window_enabled(true);
} else {
#ifdef LIMBOAI_MODULE
EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorDebuggerNode::get_singleton());
EditorNode::get_bottom_panel()->make_item_visible(EditorDebuggerNode::get_singleton());
EditorDebuggerNode::get_singleton()->get_default_debugger()->switch_to_debugger(
LimboDebuggerPlugin::get_singleton()->get_first_session_tab_index());
#elif LIMBOAI_GDEXTENSION

View File

@ -25,7 +25,7 @@
#include "core/object/object.h"
#include "core/templates/hash_set.h"
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/plugins/editor_plugin.h"
#include "editor/gui/editor_spin_slider.h"
#include "scene/gui/box_container.h"
#include "scene/gui/control.h"

View File

@ -24,7 +24,7 @@
#include "editor/editor_help.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/themes/editor_scale.h"
#include "editor/plugins/script_editor_plugin.h"
#include "scene/gui/check_box.h"
#endif // LIMBO_MODULE
@ -60,7 +60,7 @@ void TaskButton::_bind_methods() {
Control *TaskButton::_do_make_tooltip(const String &p_text) const {
#ifdef LIMBOAI_MODULE
EditorHelpBit *help_bit = memnew(EditorHelpBit);
help_bit->get_rich_text()->set_custom_minimum_size(Size2(360 * EDSCALE, 1));
help_bit->set_content_height_limits(1, 360 * EDSCALE);
String help_text;
if (!p_text.is_empty()) {
@ -69,7 +69,7 @@ Control *TaskButton::_do_make_tooltip(const String &p_text) const {
help_text = "[i]" + TTR("No description.") + "[/i]";
}
help_bit->set_text(help_text);
help_bit->set_custom_text(String(), String(), help_text);
return help_bit;
#endif // LIMBOAI_MODULE

View File

@ -20,7 +20,7 @@
#ifdef LIMBOAI_MODULE
#include "core/object/script_language.h"
#include "editor/editor_scale.h"
#include "editor/themes/editor_scale.h"
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
@ -50,7 +50,7 @@ void TaskTree::_update_item(TreeItem *p_item) {
if (p_item->get_parent()) {
Ref<BTProbabilitySelector> sel = p_item->get_parent()->get_metadata(0);
if (sel.is_valid() && sel->has_probability(p_item->get_index())) {
p_item->set_custom_draw(0, this, LW_NAME(_draw_probability));
p_item->set_custom_draw_callback(0, callable_mp(this, &TaskTree::_draw_probability));
p_item->set_cell_mode(0, TreeItem::CELL_MODE_CUSTOM);
}
}

View File

@ -27,11 +27,6 @@
LimboStringNames *LimboStringNames::singleton = nullptr;
LimboStringNames::LimboStringNames() {
_draw_failure_status = SN("_draw_failure_status");
_draw_fresh = SN("_draw_fresh");
_draw_probability = SN("_draw_probability");
_draw_running_status = SN("_draw_running_status");
_draw_success_status = SN("_draw_success_status");
_enter = SN("_enter");
_exit = SN("_exit");
_generate_name = SN("_generate_name");

View File

@ -43,11 +43,6 @@ class LimboStringNames {
public:
_FORCE_INLINE_ static LimboStringNames *get_singleton() { return singleton; }
StringName _draw_failure_status;
StringName _draw_fresh;
StringName _draw_probability;
StringName _draw_running_status;
StringName _draw_success_status;
StringName _enter;
StringName _exit;
StringName _generate_name;

View File

@ -515,6 +515,7 @@ PackedInt32Array LimboUtility::get_property_hints_allowed_for_type(Variant::Type
case Variant::Type::PACKED_STRING_ARRAY:
case Variant::Type::PACKED_VECTOR2_ARRAY:
case Variant::Type::PACKED_VECTOR3_ARRAY:
case Variant::Type::PACKED_VECTOR4_ARRAY:
case Variant::Type::PACKED_COLOR_ARRAY:
case Variant::Type::VARIANT_MAX: {
} break;