Add elapsed, timing info and improve drawing
This commit is contained in:
parent
9abfeadc21
commit
ded2ed2fef
|
@ -10,13 +10,11 @@ String BTRandomWait::_generate_name() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTRandomWait::_enter() {
|
void BTRandomWait::_enter() {
|
||||||
time_passed = 0.0;
|
|
||||||
duration = Math::random(min_duration, max_duration);
|
duration = Math::random(min_duration, max_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BTRandomWait::_tick(double p_delta) {
|
int BTRandomWait::_tick(double p_delta) {
|
||||||
time_passed += p_delta;
|
if (get_elapsed_time() < duration) {
|
||||||
if (time_passed < duration) {
|
|
||||||
return RUNNING;
|
return RUNNING;
|
||||||
} else {
|
} else {
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
|
@ -13,7 +13,6 @@ private:
|
||||||
double min_duration = 1.0;
|
double min_duration = 1.0;
|
||||||
double max_duration = 2.0;
|
double max_duration = 2.0;
|
||||||
|
|
||||||
double time_passed = 0.0;
|
|
||||||
double duration = 0.0;
|
double duration = 0.0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -10,13 +10,8 @@ String BTWait::_generate_name() const {
|
||||||
return vformat("Wait %s sec", Math::snapped(duration, 0.001));
|
return vformat("Wait %s sec", Math::snapped(duration, 0.001));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTWait::_enter() {
|
|
||||||
time_passed = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BTWait::_tick(double p_delta) {
|
int BTWait::_tick(double p_delta) {
|
||||||
time_passed += p_delta;
|
if (get_elapsed_time() < duration) {
|
||||||
if (time_passed < duration) {
|
|
||||||
return RUNNING;
|
return RUNNING;
|
||||||
} else {
|
} else {
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
|
@ -12,13 +12,10 @@ class BTWait : public BTAction {
|
||||||
private:
|
private:
|
||||||
double duration = 1.0;
|
double duration = 1.0;
|
||||||
|
|
||||||
double time_passed = 0.0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
virtual String _generate_name() const override;
|
virtual String _generate_name() const override;
|
||||||
virtual void _enter() override;
|
|
||||||
virtual int _tick(double p_delta) override;
|
virtual int _tick(double p_delta) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -132,20 +132,28 @@ Ref<BTTask> BTTask::clone() const {
|
||||||
|
|
||||||
int BTTask::execute(double p_delta) {
|
int BTTask::execute(double p_delta) {
|
||||||
if (status != RUNNING) {
|
if (status != RUNNING) {
|
||||||
|
// Reset children status.
|
||||||
|
if (status != FRESH) {
|
||||||
|
for (int i = 0; i < get_child_count(); i++) {
|
||||||
|
children.get(i)->cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!GDVIRTUAL_CALL(_enter)) {
|
if (!GDVIRTUAL_CALL(_enter)) {
|
||||||
_enter();
|
_enter();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
elapsed += p_delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GDVIRTUAL_CALL(_tick, p_delta, status)) {
|
if (!GDVIRTUAL_CALL(_tick, p_delta, status)) {
|
||||||
status = _tick(p_delta);
|
status = _tick(p_delta);
|
||||||
}
|
}
|
||||||
last_tick_usec = Engine::get_singleton()->get_frame_ticks();
|
|
||||||
|
|
||||||
if (status != RUNNING) {
|
if (status != RUNNING) {
|
||||||
if (!GDVIRTUAL_CALL(_exit)) {
|
if (!GDVIRTUAL_CALL(_exit)) {
|
||||||
_exit();
|
_exit();
|
||||||
}
|
}
|
||||||
|
elapsed = 0.0;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +168,7 @@ void BTTask::cancel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = FRESH;
|
status = FRESH;
|
||||||
|
elapsed = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<BTTask> BTTask::get_child(int p_idx) const {
|
Ref<BTTask> BTTask::get_child(int p_idx) const {
|
||||||
|
@ -277,13 +286,12 @@ void BTTask::_bind_methods() {
|
||||||
// Properties, setters and getters.
|
// Properties, setters and getters.
|
||||||
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
||||||
ClassDB::bind_method(D_METHOD("set_agent", "p_agent"), &BTTask::set_agent);
|
ClassDB::bind_method(D_METHOD("set_agent", "p_agent"), &BTTask::set_agent);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
||||||
ClassDB::bind_method(D_METHOD("_set_children", "p_children"), &BTTask::_set_children);
|
ClassDB::bind_method(D_METHOD("_set_children", "p_children"), &BTTask::_set_children);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
||||||
ClassDB::bind_method(D_METHOD("get_parent"), &BTTask::get_parent);
|
ClassDB::bind_method(D_METHOD("get_parent"), &BTTask::get_parent);
|
||||||
ClassDB::bind_method(D_METHOD("get_status"), &BTTask::get_status);
|
ClassDB::bind_method(D_METHOD("get_status"), &BTTask::get_status);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_elapsed_time"), &BTTask::get_elapsed_time);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_agent", "get_agent");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_agent", "get_agent");
|
||||||
|
@ -291,6 +299,7 @@ void BTTask::_bind_methods() {
|
||||||
// ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "BTTask", 0), "", "get_parent");
|
// ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "BTTask", 0), "", "get_parent");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", 0), "", "get_status");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", 0), "", "get_status");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "elapsed_time"), "", "get_elapsed_time");
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_setup);
|
GDVIRTUAL_BIND(_setup);
|
||||||
GDVIRTUAL_BIND(_enter);
|
GDVIRTUAL_BIND(_enter);
|
||||||
|
@ -312,7 +321,7 @@ BTTask::BTTask() {
|
||||||
parent = nullptr;
|
parent = nullptr;
|
||||||
children = Vector<Ref<BTTask>>();
|
children = Vector<Ref<BTTask>>();
|
||||||
status = FRESH;
|
status = FRESH;
|
||||||
last_tick_usec = 0;
|
elapsed = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BTTask::~BTTask() {
|
BTTask::~BTTask() {
|
||||||
|
|
|
@ -33,7 +33,7 @@ private:
|
||||||
BTTask *parent;
|
BTTask *parent;
|
||||||
Vector<Ref<BTTask>> children;
|
Vector<Ref<BTTask>> children;
|
||||||
int status;
|
int status;
|
||||||
int last_tick_usec;
|
double elapsed;
|
||||||
|
|
||||||
Array _get_children() const;
|
Array _get_children() const;
|
||||||
void _set_children(Array children);
|
void _set_children(Array children);
|
||||||
|
@ -76,7 +76,7 @@ public:
|
||||||
int execute(double p_delta);
|
int execute(double p_delta);
|
||||||
void cancel();
|
void cancel();
|
||||||
int get_status() const { return status; }
|
int get_status() const { return status; }
|
||||||
int get_last_tick_usec() const { return last_tick_usec; }
|
double get_elapsed_time() const { return elapsed; };
|
||||||
|
|
||||||
Ref<BTTask> get_child(int p_idx) const;
|
Ref<BTTask> get_child(int p_idx) const;
|
||||||
int get_child_count() const;
|
int get_child_count() const;
|
||||||
|
|
|
@ -12,14 +12,9 @@ String BTDelay::_generate_name() const {
|
||||||
return vformat("Delay %s sec", Math::snapped(seconds, 0.001));
|
return vformat("Delay %s sec", Math::snapped(seconds, 0.001));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTDelay::_enter() {
|
|
||||||
time_passed = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BTDelay::_tick(double p_delta) {
|
int BTDelay::_tick(double p_delta) {
|
||||||
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
|
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
|
||||||
time_passed += p_delta;
|
if (get_elapsed_time() <= seconds) {
|
||||||
if (time_passed <= seconds) {
|
|
||||||
return RUNNING;
|
return RUNNING;
|
||||||
}
|
}
|
||||||
return get_child(0)->execute(p_delta);
|
return get_child(0)->execute(p_delta);
|
||||||
|
|
|
@ -11,13 +11,11 @@ class BTDelay : public BTDecorator {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double seconds = 1.0;
|
double seconds = 1.0;
|
||||||
double time_passed = 0.0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
virtual String _generate_name() const override;
|
virtual String _generate_name() const override;
|
||||||
virtual void _enter() override;
|
|
||||||
virtual int _tick(double p_delta) override;
|
virtual int _tick(double p_delta) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -7,15 +7,10 @@ String BTTimeLimit::_generate_name() const {
|
||||||
return vformat("TimeLimit %s sec", Math::snapped(time_limit, 0.001));
|
return vformat("TimeLimit %s sec", Math::snapped(time_limit, 0.001));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTTimeLimit::_enter() {
|
|
||||||
time_passed = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BTTimeLimit::_tick(double p_delta) {
|
int BTTimeLimit::_tick(double p_delta) {
|
||||||
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
|
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
|
||||||
time_passed += p_delta;
|
|
||||||
int status = get_child(0)->execute(p_delta);
|
int status = get_child(0)->execute(p_delta);
|
||||||
if (status == RUNNING and time_passed >= time_limit) {
|
if (status == RUNNING and get_elapsed_time() >= time_limit) {
|
||||||
get_child(0)->cancel();
|
get_child(0)->cancel();
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,11 @@ class BTTimeLimit : public BTDecorator {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double time_limit = 5.0;
|
double time_limit = 5.0;
|
||||||
double time_passed = 0.0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
virtual String _generate_name() const override;
|
virtual String _generate_name() const override;
|
||||||
virtual void _enter() override;
|
|
||||||
virtual int _tick(double p_delta) override;
|
virtual int _tick(double p_delta) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -9,6 +9,7 @@ BehaviorTreeData::BehaviorTreeData(const Ref<BTTask> &p_instance) {
|
||||||
// Flatten tree into list depth first
|
// Flatten tree into list depth first
|
||||||
List<Ref<BTTask>> stack;
|
List<Ref<BTTask>> stack;
|
||||||
stack.push_back(p_instance);
|
stack.push_back(p_instance);
|
||||||
|
int id = 0;
|
||||||
while (stack.size()) {
|
while (stack.size()) {
|
||||||
Ref<BTTask> task = stack[0];
|
Ref<BTTask> task = stack[0];
|
||||||
stack.pop_front();
|
stack.pop_front();
|
||||||
|
@ -19,20 +20,23 @@ BehaviorTreeData::BehaviorTreeData(const Ref<BTTask> &p_instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.push_back(TaskData(
|
tasks.push_back(TaskData(
|
||||||
|
id,
|
||||||
task->get_task_name(),
|
task->get_task_name(),
|
||||||
num_children,
|
num_children,
|
||||||
task->get_status(),
|
task->get_status(),
|
||||||
task->get_last_tick_usec(),
|
task->get_elapsed_time(),
|
||||||
task->get_class()));
|
task->get_class()));
|
||||||
|
id += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BehaviorTreeData::serialize(Array &p_arr) {
|
void BehaviorTreeData::serialize(Array &p_arr) {
|
||||||
for (const TaskData &td : tasks) {
|
for (const TaskData &td : tasks) {
|
||||||
|
p_arr.push_back(td.id);
|
||||||
p_arr.push_back(td.name);
|
p_arr.push_back(td.name);
|
||||||
p_arr.push_back(td.num_children);
|
p_arr.push_back(td.num_children);
|
||||||
p_arr.push_back(td.status);
|
p_arr.push_back(td.status);
|
||||||
p_arr.push_back(td.last_tick_usec);
|
p_arr.push_back(td.elapsed_time);
|
||||||
p_arr.push_back(td.type_name);
|
p_arr.push_back(td.type_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,13 +46,14 @@ void BehaviorTreeData::deserialize(const Array &p_arr) {
|
||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while (p_arr.size() > idx) {
|
while (p_arr.size() > idx) {
|
||||||
ERR_FAIL_COND(p_arr.size() < 5);
|
ERR_FAIL_COND(p_arr.size() < 6);
|
||||||
ERR_FAIL_COND(p_arr[idx].get_type() != Variant::STRING);
|
ERR_FAIL_COND(p_arr[idx].get_type() != Variant::INT);
|
||||||
ERR_FAIL_COND(p_arr[idx + 1].get_type() != Variant::INT);
|
ERR_FAIL_COND(p_arr[idx + 1].get_type() != Variant::STRING);
|
||||||
ERR_FAIL_COND(p_arr[idx + 2].get_type() != Variant::INT);
|
ERR_FAIL_COND(p_arr[idx + 2].get_type() != Variant::INT);
|
||||||
ERR_FAIL_COND(p_arr[idx + 3].get_type() != Variant::INT);
|
ERR_FAIL_COND(p_arr[idx + 3].get_type() != Variant::INT);
|
||||||
ERR_FAIL_COND(p_arr[idx + 4].get_type() != Variant::STRING);
|
ERR_FAIL_COND(p_arr[idx + 4].get_type() != Variant::FLOAT);
|
||||||
tasks.push_back(TaskData(p_arr[idx], p_arr[idx + 1], p_arr[idx + 2], p_arr[idx + 3], p_arr[idx + 4]));
|
ERR_FAIL_COND(p_arr[idx + 5].get_type() != Variant::STRING);
|
||||||
idx += 5;
|
tasks.push_back(TaskData(p_arr[idx], p_arr[idx + 1], p_arr[idx + 2], p_arr[idx + 3], p_arr[idx + 4], p_arr[idx + 5]));
|
||||||
|
idx += 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,20 +9,21 @@
|
||||||
class BehaviorTreeData {
|
class BehaviorTreeData {
|
||||||
public:
|
public:
|
||||||
struct TaskData {
|
struct TaskData {
|
||||||
|
int id = 0;
|
||||||
String name;
|
String name;
|
||||||
// ObjectID object_id;
|
|
||||||
int num_children = 0;
|
int num_children = 0;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int last_tick_usec = 0;
|
double elapsed_time = 0.0;
|
||||||
String type_name;
|
String type_name;
|
||||||
// String script_path;
|
// String script_path;
|
||||||
// String resource_path;
|
// String resource_path;
|
||||||
|
|
||||||
TaskData(const String &p_name, int p_num_children, int p_status, int p_last_tick_usec, const String &p_type_name) {
|
TaskData(int p_id, const String &p_name, int p_num_children, int p_status, double p_elapsed_time, const String &p_type_name) {
|
||||||
|
id = p_id;
|
||||||
name = p_name;
|
name = p_name;
|
||||||
num_children = p_num_children;
|
num_children = p_num_children;
|
||||||
status = p_status;
|
status = p_status;
|
||||||
last_tick_usec = p_last_tick_usec;
|
elapsed_time = p_elapsed_time;
|
||||||
type_name = p_type_name;
|
type_name = p_type_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,51 @@
|
||||||
#include "behavior_tree_view.h"
|
#include "behavior_tree_view.h"
|
||||||
#include "behavior_tree_data.h"
|
#include "behavior_tree_data.h"
|
||||||
#include "core/math/color.h"
|
#include "core/math/color.h"
|
||||||
|
#include "core/math/math_defs.h"
|
||||||
|
#include "core/object/callable_method_pointer.h"
|
||||||
|
#include "core/typedefs.h"
|
||||||
|
#include "editor/editor_scale.h"
|
||||||
#include "modules/limboai/bt/bt_task.h"
|
#include "modules/limboai/bt/bt_task.h"
|
||||||
#include "modules/limboai/limbo_utility.h"
|
#include "modules/limboai/limbo_utility.h"
|
||||||
|
#include "scene/resources/style_box.h"
|
||||||
|
|
||||||
|
void BehaviorTreeView::_draw_running_status(Object *p_obj, Rect2 p_rect) {
|
||||||
|
p_rect = p_rect.grow_side(SIDE_LEFT, p_rect.get_position().x);
|
||||||
|
sbf_running.draw(tree->get_canvas_item(), p_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTreeView::_draw_success_status(Object *p_obj, Rect2 p_rect) {
|
||||||
|
p_rect = p_rect.grow_side(SIDE_LEFT, p_rect.get_position().x);
|
||||||
|
sbf_success.draw(tree->get_canvas_item(), p_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTreeView::_draw_failure_status(Object *p_obj, Rect2 p_rect) {
|
||||||
|
p_rect = p_rect.grow_side(SIDE_LEFT, p_rect.get_position().x);
|
||||||
|
sbf_failure.draw(tree->get_canvas_item(), p_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTreeView::_item_collapsed(Object *p_obj) {
|
||||||
|
TreeItem *item = Object::cast_to<TreeItem>(p_obj);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int id = item->get_metadata(0);
|
||||||
|
bool collapsed = item->is_collapsed();
|
||||||
|
if (!collapsed_ids.has(id) && collapsed) {
|
||||||
|
collapsed_ids.push_back(item->get_metadata(0));
|
||||||
|
} else if (collapsed_ids.has(id) && !collapsed) {
|
||||||
|
collapsed_ids.erase(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BehaviorTreeView::update_tree(const BehaviorTreeData &p_data) {
|
void BehaviorTreeView::update_tree(const BehaviorTreeData &p_data) {
|
||||||
|
// Remember selected.
|
||||||
|
int selected_id = -1;
|
||||||
|
if (tree->get_selected()) {
|
||||||
|
selected_id = tree->get_selected()->get_metadata(0);
|
||||||
|
}
|
||||||
|
|
||||||
tree->clear();
|
tree->clear();
|
||||||
int recent_tick_usec = -1;
|
|
||||||
TreeItem *parent = nullptr;
|
TreeItem *parent = nullptr;
|
||||||
List<Pair<TreeItem *, int>> parents;
|
List<Pair<TreeItem *, int>> parents;
|
||||||
for (const BehaviorTreeData::TaskData &task_data : p_data.tasks) {
|
for (const BehaviorTreeData::TaskData &task_data : p_data.tasks) {
|
||||||
|
@ -24,24 +63,28 @@ void BehaviorTreeView::update_tree(const BehaviorTreeData &p_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *item = tree->create_item(parent);
|
TreeItem *item = tree->create_item(parent);
|
||||||
|
// Do this first because it resets properties of the cell...
|
||||||
|
item->set_cell_mode(0, TreeItem::CELL_MODE_CUSTOM);
|
||||||
|
|
||||||
|
item->set_metadata(0, task_data.id);
|
||||||
item->set_text(0, task_data.name);
|
item->set_text(0, task_data.name);
|
||||||
item->set_icon(0, LimboUtility::get_singleton()->get_task_icon(task_data.type_name));
|
item->set_icon(0, LimboUtility::get_singleton()->get_task_icon(task_data.type_name));
|
||||||
|
item->set_text(1, rtos(Math::snapped(task_data.elapsed_time, 0.01)));
|
||||||
|
|
||||||
// First task in list is the root task and has most recent tick time.
|
if (task_data.status == BTTask::SUCCESS) {
|
||||||
if (recent_tick_usec == -1) {
|
item->set_custom_draw(0, this, SNAME("_draw_success_status"));
|
||||||
recent_tick_usec = task_data.last_tick_usec;
|
} else if (task_data.status == BTTask::FAILURE) {
|
||||||
|
item->set_custom_draw(0, this, SNAME("_draw_failure_status"));
|
||||||
|
} else if (task_data.status == BTTask::RUNNING) {
|
||||||
|
item->set_custom_draw(0, this, SNAME("_draw_running_status"));
|
||||||
}
|
}
|
||||||
// Item BG color depends on age of the task status.
|
|
||||||
int timediff = recent_tick_usec - task_data.last_tick_usec;
|
if (task_data.id == selected_id) {
|
||||||
if (timediff <= 300000) {
|
tree->set_selected(item);
|
||||||
float alpha = (300000 - timediff) / 300000.0;
|
}
|
||||||
if (task_data.status == BTTask::SUCCESS) {
|
|
||||||
item->set_custom_bg_color(0, Color(0, 0.5, 0, alpha));
|
if (collapsed_ids.has(task_data.id)) {
|
||||||
} else if (task_data.status == BTTask::FAILURE) {
|
item->set_collapsed(true);
|
||||||
item->set_custom_bg_color(0, Color(0.5, 0, 0, alpha));
|
|
||||||
} else if (task_data.status == BTTask::RUNNING) {
|
|
||||||
item->set_custom_bg_color(0, Color(0.5, 0.5, 0, alpha));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add in front of parents stack if it expects children.
|
// Add in front of parents stack if it expects children.
|
||||||
|
@ -53,13 +96,40 @@ void BehaviorTreeView::update_tree(const BehaviorTreeData &p_data) {
|
||||||
|
|
||||||
void BehaviorTreeView::clear() {
|
void BehaviorTreeView::clear() {
|
||||||
tree->clear();
|
tree->clear();
|
||||||
|
collapsed_ids.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTreeView::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("_draw_running_status"), &BehaviorTreeView::_draw_running_status);
|
||||||
|
ClassDB::bind_method(D_METHOD("_draw_success_status"), &BehaviorTreeView::_draw_success_status);
|
||||||
|
ClassDB::bind_method(D_METHOD("_draw_failure_status"), &BehaviorTreeView::_draw_failure_status);
|
||||||
|
ClassDB::bind_method(D_METHOD("_item_collapsed"), &BehaviorTreeView::_item_collapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
BehaviorTreeView::BehaviorTreeView() {
|
BehaviorTreeView::BehaviorTreeView() {
|
||||||
tree = memnew(Tree);
|
tree = memnew(Tree);
|
||||||
add_child(tree);
|
add_child(tree);
|
||||||
tree->set_columns(1);
|
tree->set_columns(2);
|
||||||
tree->set_column_expand(0, true);
|
tree->set_column_expand(0, true);
|
||||||
|
tree->set_column_expand(1, false);
|
||||||
|
tree->set_column_custom_minimum_width(1, 40.0 * EDSCALE);
|
||||||
tree->set_anchor(SIDE_RIGHT, ANCHOR_END);
|
tree->set_anchor(SIDE_RIGHT, ANCHOR_END);
|
||||||
tree->set_anchor(SIDE_BOTTOM, ANCHOR_END);
|
tree->set_anchor(SIDE_BOTTOM, ANCHOR_END);
|
||||||
|
|
||||||
|
sbf_running.set_border_color(Color(1.0, 1.0, 0.0));
|
||||||
|
sbf_running.set_bg_color(Color(1.0, 1.0, 0, 0.1));
|
||||||
|
sbf_running.set_border_width(SIDE_LEFT, 4.0);
|
||||||
|
sbf_running.set_border_width(SIDE_RIGHT, 4.0);
|
||||||
|
|
||||||
|
sbf_success.set_border_color(Color(0.0, 0.8, 0.0));
|
||||||
|
sbf_success.set_bg_color(Color(0.0, 0.8, 0.0, 0.1));
|
||||||
|
sbf_success.set_border_width(SIDE_LEFT, 4.0);
|
||||||
|
sbf_success.set_border_width(SIDE_RIGHT, 4.0);
|
||||||
|
|
||||||
|
sbf_failure.set_border_color(Color(1.0, 0.0, 0.0));
|
||||||
|
sbf_failure.set_bg_color(Color(1.0, 0.0, 0.0, 0.1));
|
||||||
|
sbf_failure.set_border_width(SIDE_LEFT, 4.0);
|
||||||
|
sbf_failure.set_border_width(SIDE_RIGHT, 4.0);
|
||||||
|
|
||||||
|
tree->connect(SNAME("item_collapsed"), callable_mp(this, &BehaviorTreeView::_item_collapsed));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,31 @@
|
||||||
#include "core/object/object.h"
|
#include "core/object/object.h"
|
||||||
#include "scene/gui/control.h"
|
#include "scene/gui/control.h"
|
||||||
#include "scene/gui/tree.h"
|
#include "scene/gui/tree.h"
|
||||||
|
#include "scene/resources/style_box.h"
|
||||||
|
|
||||||
class BehaviorTreeView : public Control {
|
class BehaviorTreeView : public Control {
|
||||||
GDCLASS(BehaviorTreeView, Control);
|
GDCLASS(BehaviorTreeView, Control);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tree *tree;
|
Tree *tree;
|
||||||
|
StyleBoxFlat sbf_running;
|
||||||
|
StyleBoxFlat sbf_success;
|
||||||
|
StyleBoxFlat sbf_failure;
|
||||||
|
Vector<int> collapsed_ids;
|
||||||
|
|
||||||
|
void _draw_success_status(Object *p_obj, Rect2 p_rect);
|
||||||
|
void _draw_running_status(Object *p_obj, Rect2 p_rect);
|
||||||
|
void _draw_failure_status(Object *p_obj, Rect2 p_rect);
|
||||||
|
void _item_collapsed(Object *p_obj);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BehaviorTreeView();
|
|
||||||
|
|
||||||
void update_tree(const BehaviorTreeData &p_data);
|
void update_tree(const BehaviorTreeData &p_data);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
BehaviorTreeView();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BEHAVIOR_TREE_VIEW
|
#endif // BEHAVIOR_TREE_VIEW
|
|
@ -73,6 +73,7 @@
|
||||||
#include "bt/decorators/bt_time_limit.h"
|
#include "bt/decorators/bt_time_limit.h"
|
||||||
#include "core/os/memory.h"
|
#include "core/os/memory.h"
|
||||||
#include "core/string/print_string.h"
|
#include "core/string/print_string.h"
|
||||||
|
#include "debugger/behavior_tree_view.h"
|
||||||
#include "limbo_hsm.h"
|
#include "limbo_hsm.h"
|
||||||
#include "limbo_state.h"
|
#include "limbo_state.h"
|
||||||
#include "limbo_string_names.h"
|
#include "limbo_string_names.h"
|
||||||
|
@ -167,6 +168,8 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
|
||||||
GDREGISTER_CLASS(BBVector3Array);
|
GDREGISTER_CLASS(BBVector3Array);
|
||||||
GDREGISTER_CLASS(BBVariant);
|
GDREGISTER_CLASS(BBVariant);
|
||||||
|
|
||||||
|
GDREGISTER_CLASS(BehaviorTreeView);
|
||||||
|
|
||||||
_limbo_utility = memnew(LimboUtility);
|
_limbo_utility = memnew(LimboUtility);
|
||||||
GDREGISTER_CLASS(LimboUtility);
|
GDREGISTER_CLASS(LimboUtility);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue