Add `LimboTaskDB` to handle task categories and scanning user tasks
This commit is contained in:
parent
26b9327090
commit
2ffcbf0565
|
@ -20,6 +20,7 @@
|
|||
|
||||
class BTAwaitAnimation : public BTAction {
|
||||
GDCLASS(BTAwaitAnimation, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTCallMethod : public BTAction {
|
||||
GDCLASS(BTCallMethod, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
StringName method_name;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTConsolePrint : public BTAction {
|
||||
GDCLASS(BTConsolePrint, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
String text;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTFail : public BTAction {
|
||||
GDCLASS(BTFail, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
protected:
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
class BTPauseAnimation : public BTAction {
|
||||
GDCLASS(BTPauseAnimation, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
class BTPlayAnimation : public BTAction {
|
||||
GDCLASS(BTPlayAnimation, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTRandomWait : public BTAction {
|
||||
GDCLASS(BTRandomWait, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
double min_duration = 1.0;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTSetAgentProperty : public BTAction {
|
||||
GDCLASS(BTSetAgentProperty, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
StringName property;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
* https://opensource.org/licenses/MIT.
|
||||
* =============================================================================
|
||||
*/
|
||||
/* bt_set_var.h */
|
||||
|
||||
#ifndef BT_SET_VAR_H
|
||||
#define BT_SET_VAR_H
|
||||
|
@ -21,6 +20,7 @@
|
|||
|
||||
class BTSetVar : public BTAction {
|
||||
GDCLASS(BTSetVar, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
String variable;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
class BTStopAnimation : public BTAction {
|
||||
GDCLASS(BTStopAnimation, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTWait : public BTAction {
|
||||
GDCLASS(BTWait, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
double duration = 1.0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTWaitTicks : public BTAction {
|
||||
GDCLASS(BTWaitTicks, BTAction);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
int num_ticks = 1;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
* https://opensource.org/licenses/MIT.
|
||||
* =============================================================================
|
||||
*/
|
||||
/* bt_comment.h */
|
||||
|
||||
#ifndef BT_COMMENT_H
|
||||
#define BT_COMMENT_H
|
||||
|
@ -18,8 +17,9 @@
|
|||
class BTComment : public BTTask {
|
||||
GDCLASS(BTComment, BTTask);
|
||||
|
||||
private:
|
||||
public:
|
||||
static _FORCE_INLINE_ String get_task_category() { return LimboTaskDB::get_misc_category(); }
|
||||
|
||||
virtual Ref<BTTask> clone() const override;
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define BTTASK_H
|
||||
|
||||
#include "modules/limboai/blackboard/blackboard.h"
|
||||
#include "modules/limboai/util/limbo_task_db.h"
|
||||
|
||||
#include "core/io/resource.h"
|
||||
#include "core/object/object.h"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTDynamicSelector : public BTComposite {
|
||||
GDCLASS(BTDynamicSelector, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int last_running_idx = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTDynamicSequence : public BTComposite {
|
||||
GDCLASS(BTDynamicSequence, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int last_running_idx = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTParallel : public BTComposite {
|
||||
GDCLASS(BTParallel, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int num_successes_required = 1;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTRandomSelector : public BTComposite {
|
||||
GDCLASS(BTRandomSelector, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int last_running_idx = 0;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTRandomSequence : public BTComposite {
|
||||
GDCLASS(BTRandomSequence, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int last_running_idx = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTSelector : public BTComposite {
|
||||
GDCLASS(BTSelector, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int last_running_idx = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTSequence : public BTComposite {
|
||||
GDCLASS(BTSequence, BTComposite);
|
||||
TASK_CATEGORY(Composites);
|
||||
|
||||
private:
|
||||
int last_running_idx = 0;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
class BTCheckAgentProperty : public BTCondition {
|
||||
GDCLASS(BTCheckAgentProperty, BTCondition);
|
||||
TASK_CATEGORY(Conditions);
|
||||
|
||||
private:
|
||||
StringName property;
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
* =============================================================================
|
||||
*/
|
||||
|
||||
/* bt_check_trigger.h */
|
||||
|
||||
#ifndef BT_CHECK_TRIGGER_H
|
||||
#define BT_CHECK_TRIGGER_H
|
||||
|
||||
|
@ -20,6 +18,7 @@
|
|||
|
||||
class BTCheckTrigger : public BTCondition {
|
||||
GDCLASS(BTCheckTrigger, BTCondition);
|
||||
TASK_CATEGORY(Conditions);
|
||||
|
||||
private:
|
||||
String variable;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
class BTCheckVar : public BTCondition {
|
||||
GDCLASS(BTCheckVar, BTCondition);
|
||||
TASK_CATEGORY(Conditions);
|
||||
|
||||
private:
|
||||
String variable;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTAlwaysFail : public BTDecorator {
|
||||
GDCLASS(BTAlwaysFail, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
protected:
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTAlwaysSucceed : public BTDecorator {
|
||||
GDCLASS(BTAlwaysSucceed, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
protected:
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTCooldown : public BTDecorator {
|
||||
GDCLASS(BTCooldown, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
double duration = 10.0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTDelay : public BTDecorator {
|
||||
GDCLASS(BTDelay, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
double seconds = 1.0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTForEach : public BTDecorator {
|
||||
GDCLASS(BTForEach, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
String array_var;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTInvert : public BTDecorator {
|
||||
GDCLASS(BTInvert, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
protected:
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTNewScope : public BTDecorator {
|
||||
GDCLASS(BTNewScope, BTDecorator);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
Dictionary blackboard_data;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTProbability : public BTDecorator {
|
||||
GDCLASS(BTProbability, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
float run_chance = 0.5;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTRepeat : public BTDecorator {
|
||||
GDCLASS(BTRepeat, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
bool forever = false;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTRepeatUntilFailure : public BTDecorator {
|
||||
GDCLASS(BTRepeatUntilFailure, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
protected:
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTRepeatUntilSuccess : public BTDecorator {
|
||||
GDCLASS(BTRepeatUntilSuccess, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
protected:
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTRunLimit : public BTDecorator {
|
||||
GDCLASS(BTRunLimit, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
int run_limit = 1;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
class BTSubtree : public BTNewScope {
|
||||
GDCLASS(BTSubtree, BTNewScope);
|
||||
TASK_CATEGORY(Actions);
|
||||
|
||||
private:
|
||||
Ref<BehaviorTree> subtree;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class BTTimeLimit : public BTDecorator {
|
||||
GDCLASS(BTTimeLimit, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
double time_limit = 5.0;
|
||||
|
|
|
@ -563,39 +563,12 @@ void TaskPanel::refresh() {
|
|||
}
|
||||
}
|
||||
|
||||
HashMap<String, List<String>> categorized_tasks;
|
||||
|
||||
categorized_tasks["Composites"] = List<String>();
|
||||
_populate_core_tasks_from_class("BTComposite", &categorized_tasks["Composites"]);
|
||||
|
||||
categorized_tasks["Actions"] = List<String>();
|
||||
_populate_core_tasks_from_class("BTAction", &categorized_tasks["Actions"]);
|
||||
|
||||
categorized_tasks["Decorators"] = List<String>();
|
||||
_populate_core_tasks_from_class("BTDecorator", &categorized_tasks["Decorators"]);
|
||||
|
||||
categorized_tasks["Conditions"] = List<String>();
|
||||
_populate_core_tasks_from_class("BTCondition", &categorized_tasks["Conditions"]);
|
||||
|
||||
categorized_tasks["Uncategorized"] = List<String>();
|
||||
|
||||
String dir1 = GLOBAL_GET("limbo_ai/behavior_tree/user_task_dir_1");
|
||||
_populate_from_user_dir(dir1, &categorized_tasks);
|
||||
|
||||
String dir2 = GLOBAL_GET("limbo_ai/behavior_tree/user_task_dir_2");
|
||||
_populate_from_user_dir(dir2, &categorized_tasks);
|
||||
|
||||
String dir3 = GLOBAL_GET("limbo_ai/behavior_tree/user_task_dir_3");
|
||||
_populate_from_user_dir(dir3, &categorized_tasks);
|
||||
|
||||
List<String> categories;
|
||||
for (KeyValue<String, List<String>> &K : categorized_tasks) {
|
||||
K.value.sort();
|
||||
categories.push_back(K.key);
|
||||
}
|
||||
LimboTaskDB::scan_user_tasks();
|
||||
List<String> categories = LimboTaskDB::get_categories();
|
||||
categories.sort();
|
||||
|
||||
for (String cat : categories) {
|
||||
List<String> tasks = categorized_tasks.get(cat);
|
||||
List<String> tasks = LimboTaskDB::get_tasks_in_category(cat);
|
||||
|
||||
if (tasks.size() == 0) {
|
||||
continue;
|
||||
|
@ -642,70 +615,6 @@ void TaskPanel::refresh() {
|
|||
}
|
||||
}
|
||||
|
||||
void TaskPanel::_populate_core_tasks_from_class(const StringName &p_base_class, List<String> *p_task_classes) {
|
||||
List<StringName> inheriters;
|
||||
ClassDB::get_inheriters_from_class(p_base_class, &inheriters);
|
||||
|
||||
for (StringName cl : inheriters) {
|
||||
p_task_classes->push_back(cl);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskPanel::_populate_from_user_dir(String p_path, HashMap<String, List<String>> *p_categories) {
|
||||
if (p_path.is_empty()) {
|
||||
return;
|
||||
}
|
||||
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
if (dir->change_dir(p_path) == OK) {
|
||||
dir->list_dir_begin();
|
||||
String fn = dir->get_next();
|
||||
while (!fn.is_empty()) {
|
||||
if (dir->current_is_dir() && fn != "..") {
|
||||
String full_path;
|
||||
String category;
|
||||
if (fn == ".") {
|
||||
full_path = p_path;
|
||||
category = "Uncategorized";
|
||||
} else {
|
||||
full_path = p_path.path_join(fn);
|
||||
category = fn.capitalize();
|
||||
}
|
||||
|
||||
if (!p_categories->has(category)) {
|
||||
p_categories->insert(category, List<String>());
|
||||
}
|
||||
|
||||
_populate_scripted_tasks_from_dir(full_path, &p_categories->get(category));
|
||||
}
|
||||
fn = dir->get_next();
|
||||
}
|
||||
dir->list_dir_end();
|
||||
} else {
|
||||
ERR_FAIL_MSG(vformat("Failed to list \"%s\" directory.", p_path));
|
||||
}
|
||||
}
|
||||
|
||||
void TaskPanel::_populate_scripted_tasks_from_dir(String p_path, List<String> *p_task_classes) {
|
||||
if (p_path.is_empty()) {
|
||||
return;
|
||||
}
|
||||
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
if (dir->change_dir(p_path) == OK) {
|
||||
dir->list_dir_begin();
|
||||
String fn = dir->get_next();
|
||||
while (!fn.is_empty()) {
|
||||
if (fn.ends_with(".gd")) {
|
||||
String full_path = p_path.path_join(fn);
|
||||
p_task_classes->push_back(full_path);
|
||||
}
|
||||
fn = dir->get_next();
|
||||
}
|
||||
dir->list_dir_end();
|
||||
} else {
|
||||
ERR_FAIL_MSG(vformat("Failed to list \"%s\" directory.", p_path));
|
||||
}
|
||||
}
|
||||
|
||||
void TaskPanel::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
|
|
|
@ -129,9 +129,6 @@ private:
|
|||
|
||||
String context_task;
|
||||
|
||||
void _populate_core_tasks_from_class(const StringName &p_base_class, List<String> *p_task_classes);
|
||||
void _populate_from_user_dir(String p_path, HashMap<String, List<String>> *p_categories);
|
||||
void _populate_scripted_tasks_from_dir(String p_path, List<String> *p_task_classes);
|
||||
void _menu_action_selected(int p_id);
|
||||
void _on_task_button_pressed(const String &p_task);
|
||||
void _on_task_button_rmb(const String &p_task);
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
#include "hsm/limbo_hsm.h"
|
||||
#include "hsm/limbo_state.h"
|
||||
#include "util/limbo_string_names.h"
|
||||
#include "util/limbo_task_db.h"
|
||||
#include "util/limbo_utility.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
@ -121,51 +122,51 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
|
|||
GDREGISTER_CLASS(BTPlayer);
|
||||
GDREGISTER_CLASS(BTState);
|
||||
|
||||
GDREGISTER_CLASS(BTComment);
|
||||
LIMBO_REGISTER_TASK(BTComment);
|
||||
|
||||
GDREGISTER_CLASS(BTComposite);
|
||||
GDREGISTER_CLASS(BTSequence);
|
||||
GDREGISTER_CLASS(BTSelector);
|
||||
GDREGISTER_CLASS(BTParallel);
|
||||
GDREGISTER_CLASS(BTDynamicSequence);
|
||||
GDREGISTER_CLASS(BTDynamicSelector);
|
||||
GDREGISTER_CLASS(BTRandomSequence);
|
||||
GDREGISTER_CLASS(BTRandomSelector);
|
||||
LIMBO_REGISTER_TASK(BTSequence);
|
||||
LIMBO_REGISTER_TASK(BTSelector);
|
||||
LIMBO_REGISTER_TASK(BTParallel);
|
||||
LIMBO_REGISTER_TASK(BTDynamicSequence);
|
||||
LIMBO_REGISTER_TASK(BTDynamicSelector);
|
||||
LIMBO_REGISTER_TASK(BTRandomSequence);
|
||||
LIMBO_REGISTER_TASK(BTRandomSelector);
|
||||
|
||||
GDREGISTER_CLASS(BTDecorator);
|
||||
GDREGISTER_CLASS(BTInvert);
|
||||
GDREGISTER_CLASS(BTAlwaysFail);
|
||||
GDREGISTER_CLASS(BTAlwaysSucceed);
|
||||
GDREGISTER_CLASS(BTDelay);
|
||||
GDREGISTER_CLASS(BTRepeat);
|
||||
GDREGISTER_CLASS(BTRepeatUntilFailure);
|
||||
GDREGISTER_CLASS(BTRepeatUntilSuccess);
|
||||
GDREGISTER_CLASS(BTRunLimit);
|
||||
GDREGISTER_CLASS(BTTimeLimit);
|
||||
GDREGISTER_CLASS(BTCooldown);
|
||||
GDREGISTER_CLASS(BTProbability);
|
||||
GDREGISTER_CLASS(BTForEach);
|
||||
LIMBO_REGISTER_TASK(BTInvert);
|
||||
LIMBO_REGISTER_TASK(BTAlwaysFail);
|
||||
LIMBO_REGISTER_TASK(BTAlwaysSucceed);
|
||||
LIMBO_REGISTER_TASK(BTDelay);
|
||||
LIMBO_REGISTER_TASK(BTRepeat);
|
||||
LIMBO_REGISTER_TASK(BTRepeatUntilFailure);
|
||||
LIMBO_REGISTER_TASK(BTRepeatUntilSuccess);
|
||||
LIMBO_REGISTER_TASK(BTRunLimit);
|
||||
LIMBO_REGISTER_TASK(BTTimeLimit);
|
||||
LIMBO_REGISTER_TASK(BTCooldown);
|
||||
LIMBO_REGISTER_TASK(BTProbability);
|
||||
LIMBO_REGISTER_TASK(BTForEach);
|
||||
|
||||
GDREGISTER_CLASS(BTAction);
|
||||
GDREGISTER_CLASS(BTAwaitAnimation);
|
||||
GDREGISTER_CLASS(BTCallMethod);
|
||||
GDREGISTER_CLASS(BTConsolePrint);
|
||||
GDREGISTER_CLASS(BTFail);
|
||||
GDREGISTER_CLASS(BTNewScope);
|
||||
GDREGISTER_CLASS(BTPauseAnimation);
|
||||
GDREGISTER_CLASS(BTPlayAnimation);
|
||||
GDREGISTER_CLASS(BTRandomWait);
|
||||
GDREGISTER_CLASS(BTSetAgentProperty);
|
||||
GDREGISTER_CLASS(BTSetVar);
|
||||
GDREGISTER_CLASS(BTStopAnimation);
|
||||
GDREGISTER_CLASS(BTSubtree);
|
||||
GDREGISTER_CLASS(BTWait);
|
||||
GDREGISTER_CLASS(BTWaitTicks);
|
||||
LIMBO_REGISTER_TASK(BTAwaitAnimation);
|
||||
LIMBO_REGISTER_TASK(BTCallMethod);
|
||||
LIMBO_REGISTER_TASK(BTConsolePrint);
|
||||
LIMBO_REGISTER_TASK(BTFail);
|
||||
LIMBO_REGISTER_TASK(BTNewScope);
|
||||
LIMBO_REGISTER_TASK(BTPauseAnimation);
|
||||
LIMBO_REGISTER_TASK(BTPlayAnimation);
|
||||
LIMBO_REGISTER_TASK(BTRandomWait);
|
||||
LIMBO_REGISTER_TASK(BTSetAgentProperty);
|
||||
LIMBO_REGISTER_TASK(BTSetVar);
|
||||
LIMBO_REGISTER_TASK(BTStopAnimation);
|
||||
LIMBO_REGISTER_TASK(BTSubtree);
|
||||
LIMBO_REGISTER_TASK(BTWait);
|
||||
LIMBO_REGISTER_TASK(BTWaitTicks);
|
||||
|
||||
GDREGISTER_CLASS(BTCondition);
|
||||
GDREGISTER_CLASS(BTCheckAgentProperty);
|
||||
GDREGISTER_CLASS(BTCheckTrigger);
|
||||
GDREGISTER_CLASS(BTCheckVar);
|
||||
LIMBO_REGISTER_TASK(BTCheckAgentProperty);
|
||||
LIMBO_REGISTER_TASK(BTCheckTrigger);
|
||||
LIMBO_REGISTER_TASK(BTCheckVar);
|
||||
|
||||
GDREGISTER_ABSTRACT_CLASS(BBParam);
|
||||
GDREGISTER_CLASS(BBInt);
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* limbo_task_db.cpp
|
||||
* =============================================================================
|
||||
* Copyright 2021-2023 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 "limbo_task_db.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
|
||||
HashMap<String, List<String>> LimboTaskDB::core_tasks;
|
||||
HashMap<String, List<String>> LimboTaskDB::tasks_cache;
|
||||
|
||||
_FORCE_INLINE_ void _populate_scripted_tasks_from_dir(String p_path, List<String> *p_task_classes) {
|
||||
if (p_path.is_empty()) {
|
||||
return;
|
||||
}
|
||||
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
if (dir->change_dir(p_path) == OK) {
|
||||
dir->list_dir_begin();
|
||||
String fn = dir->get_next();
|
||||
while (!fn.is_empty()) {
|
||||
if (fn.ends_with(".gd")) {
|
||||
String full_path = p_path.path_join(fn);
|
||||
p_task_classes->push_back(full_path);
|
||||
}
|
||||
fn = dir->get_next();
|
||||
}
|
||||
dir->list_dir_end();
|
||||
} else {
|
||||
ERR_FAIL_MSG(vformat("Failed to list \"%s\" directory.", p_path));
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void _populate_from_user_dir(String p_path, HashMap<String, List<String>> *p_categories) {
|
||||
if (p_path.is_empty()) {
|
||||
return;
|
||||
}
|
||||
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
if (dir->change_dir(p_path) == OK) {
|
||||
dir->list_dir_begin();
|
||||
String fn = dir->get_next();
|
||||
while (!fn.is_empty()) {
|
||||
if (dir->current_is_dir() && fn != "..") {
|
||||
String full_path;
|
||||
String category;
|
||||
if (fn == ".") {
|
||||
full_path = p_path;
|
||||
category = LimboTaskDB::get_misc_category();
|
||||
} else {
|
||||
full_path = p_path.path_join(fn);
|
||||
category = fn.capitalize();
|
||||
}
|
||||
|
||||
if (!p_categories->has(category)) {
|
||||
p_categories->insert(category, List<String>());
|
||||
}
|
||||
|
||||
_populate_scripted_tasks_from_dir(full_path, &p_categories->get(category));
|
||||
}
|
||||
fn = dir->get_next();
|
||||
}
|
||||
dir->list_dir_end();
|
||||
} else {
|
||||
ERR_FAIL_MSG(vformat("Failed to list \"%s\" directory.", p_path));
|
||||
}
|
||||
}
|
||||
|
||||
void LimboTaskDB::scan_user_tasks() {
|
||||
tasks_cache = HashMap<String, List<String>>(core_tasks);
|
||||
|
||||
if (!tasks_cache.has(LimboTaskDB::get_misc_category())) {
|
||||
tasks_cache[LimboTaskDB::get_misc_category()] = List<String>();
|
||||
}
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
String dir1 = GLOBAL_GET("limbo_ai/behavior_tree/user_task_dir_" + itos(i));
|
||||
_populate_from_user_dir(dir1, &tasks_cache);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> LimboTaskDB::get_categories() {
|
||||
List<String> r_cat;
|
||||
for (const KeyValue<String, List<String>> &E : tasks_cache) {
|
||||
r_cat.push_back(E.key);
|
||||
}
|
||||
return r_cat;
|
||||
}
|
||||
|
||||
List<String> LimboTaskDB::get_tasks_in_category(const String &p_category) {
|
||||
return List<String>(tasks_cache[p_category]);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* limbo_task_db.h
|
||||
* =============================================================================
|
||||
* Copyright 2021-2023 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 LIMBO_TASK_DB_H
|
||||
#define LIMBO_TASK_DB_H
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/list.h"
|
||||
|
||||
class LimboTaskDB {
|
||||
private:
|
||||
static HashMap<String, List<String>> core_tasks;
|
||||
static HashMap<String, List<String>> tasks_cache;
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
static void register_task() {
|
||||
GDREGISTER_CLASS(T);
|
||||
HashMap<String, List<String>>::Iterator E = core_tasks.find(T::get_task_category());
|
||||
if (E) {
|
||||
E->value.push_back(T::get_class_static());
|
||||
} else {
|
||||
List<String> tasks;
|
||||
tasks.push_back(T::get_class_static());
|
||||
core_tasks.insert(T::get_task_category(), tasks);
|
||||
}
|
||||
}
|
||||
|
||||
static void scan_user_tasks();
|
||||
static _FORCE_INLINE_ String get_misc_category() { return "Misc"; }
|
||||
static List<String> get_categories();
|
||||
static List<String> get_tasks_in_category(const String &p_category);
|
||||
};
|
||||
|
||||
#define LIMBO_REGISTER_TASK(m_class) \
|
||||
if (m_class::_class_is_enabled) { \
|
||||
::LimboTaskDB::register_task<m_class>(); \
|
||||
}
|
||||
|
||||
#define TASK_CATEGORY(m_cat) \
|
||||
public: \
|
||||
static _FORCE_INLINE_ String get_task_category() { \
|
||||
return String(#m_cat); \
|
||||
} \
|
||||
\
|
||||
private:
|
||||
|
||||
#endif // LIMBO_TASK_DB_H
|
Loading…
Reference in New Issue