Make blackboard improvements compatible with GDExtension

This commit is contained in:
Serhii Snitsaruk 2024-01-25 17:59:38 +01:00
parent a251d92aa3
commit 5fee89b00b
10 changed files with 165 additions and 105 deletions

View File

@ -12,9 +12,18 @@
#ifndef BB_VARIABLE_H #ifndef BB_VARIABLE_H
#define BB_VARIABLE_H #define BB_VARIABLE_H
#ifdef LIMBOAI_MODULE
#include "core/object/object.h" #include "core/object/object.h"
#include "core/templates/safe_refcount.h" #include "core/templates/safe_refcount.h"
#include "core/variant/variant.h" #include "core/variant/variant.h"
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include "godot_cpp/core/defs.hpp"
#include "godot_cpp/templates/safe_refcount.hpp"
#include "godot_cpp/variant/variant.hpp"
using namespace godot;
#endif // LIMBOAI_GDEXTENSION
class BBVariable { class BBVariable {
private: private:

View File

@ -22,7 +22,6 @@
#include <godot_cpp/classes/ref.hpp> #include <godot_cpp/classes/ref.hpp>
#include <godot_cpp/classes/ref_counted.hpp> #include <godot_cpp/classes/ref_counted.hpp>
#include <godot_cpp/core/object.hpp> #include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/dictionary.hpp>
using namespace godot; using namespace godot;
#endif #endif

View File

@ -17,7 +17,6 @@
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
#include "core/object/object.h" #include "core/object/object.h"
#include "core/object/ref_counted.h" #include "core/object/ref_counted.h"
#include "core/variant/dictionary.h"
#include "core/variant/variant.h" #include "core/variant/variant.h"
#include "scene/main/node.h" #include "scene/main/node.h"
#endif // LIMBOAI_MODULE #endif // LIMBOAI_MODULE
@ -27,7 +26,7 @@
#include <godot_cpp/classes/ref.hpp> #include <godot_cpp/classes/ref.hpp>
#include <godot_cpp/classes/ref_counted.hpp> #include <godot_cpp/classes/ref_counted.hpp>
#include <godot_cpp/core/object.hpp> #include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/dictionary.hpp> #include <godot_cpp/templates/hash_map.hpp>
using namespace godot; using namespace godot;
#endif // LIMBOAI_GDEXTENSION #endif // LIMBOAI_GDEXTENSION

View File

@ -15,8 +15,8 @@ bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
String prop_name = p_name; String prop_name = p_name;
// * Editor // * Editor
if (data.has(prop_name)) { if (var_map.has(prop_name)) {
data[prop_name].set_value(p_value); var_map[prop_name].set_value(p_value);
return true; return true;
} }
@ -24,19 +24,19 @@ bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
if (prop_name.begins_with("var/")) { if (prop_name.begins_with("var/")) {
String var_name = prop_name.get_slicec('/', 1); String var_name = prop_name.get_slicec('/', 1);
String what = prop_name.get_slicec('/', 2); String what = prop_name.get_slicec('/', 2);
if (!data.has(var_name) && what == "name") { if (!var_map.has(var_name) && what == "name") {
data.insert(var_name, BBVariable()); add_var(var_name, BBVariable());
} }
if (what == "name") { if (what == "name") {
// We don't store variable name with the variable. // We don't store variable name with the variable.
} else if (what == "type") { } else if (what == "type") {
data[var_name].set_type((Variant::Type)(int)p_value); var_map[var_name].set_type((Variant::Type)(int)p_value);
} else if (what == "value") { } else if (what == "value") {
data[var_name].set_value(p_value); var_map[var_name].set_value(p_value);
} else if (what == "hint") { } else if (what == "hint") {
data[var_name].set_hint((PropertyHint)(int)p_value); var_map[var_name].set_hint((PropertyHint)(int)p_value);
} else if (what == "hint_string") { } else if (what == "hint_string") {
data[var_name].set_hint_string(p_value); var_map[var_name].set_hint_string(p_value);
} else { } else {
return false; return false;
} }
@ -50,8 +50,8 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const {
String prop_name = p_name; String prop_name = p_name;
// * Editor // * Editor
if (data.has(prop_name)) { if (var_map.has(prop_name)) {
r_ret = data[prop_name].get_value(); r_ret = var_map[prop_name].get_value();
return true; return true;
} }
@ -62,26 +62,26 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const {
String var_name = prop_name.get_slicec('/', 1); String var_name = prop_name.get_slicec('/', 1);
String what = prop_name.get_slicec('/', 2); String what = prop_name.get_slicec('/', 2);
ERR_FAIL_COND_V(!data.has(var_name), false); ERR_FAIL_COND_V(!var_map.has(var_name), false);
if (what == "name") { if (what == "name") {
r_ret = var_name; r_ret = var_name;
} else if (what == "type") { } else if (what == "type") {
r_ret = data[var_name].get_type(); r_ret = var_map[var_name].get_type();
} else if (what == "value") { } else if (what == "value") {
r_ret = data[var_name].get_value(); r_ret = var_map[var_name].get_value();
} else if (what == "hint") { } else if (what == "hint") {
r_ret = data[var_name].get_hint(); r_ret = var_map[var_name].get_hint();
} else if (what == "hint_string") { } else if (what == "hint_string") {
r_ret = data[var_name].get_hint_string(); r_ret = var_map[var_name].get_hint_string();
} }
return true; return true;
} }
void BlackboardPlan::_get_property_list(List<PropertyInfo> *p_list) const { void BlackboardPlan::_get_property_list(List<PropertyInfo> *p_list) const {
for (const KeyValue<String, BBVariable> &kv : data) { for (const Pair<String, BBVariable> &p : var_list) {
String var_name = kv.key; String var_name = p.first;
BBVariable var = kv.value; BBVariable var = p.second;
// * Editor // * Editor
if (!is_derived() || !var_name.begins_with("_")) { if (!is_derived() || !var_name.begins_with("_")) {
@ -98,12 +98,12 @@ void BlackboardPlan::_get_property_list(List<PropertyInfo> *p_list) const {
} }
bool BlackboardPlan::_property_can_revert(const StringName &p_name) const { bool BlackboardPlan::_property_can_revert(const StringName &p_name) const {
return base.is_valid() && base->data.has(p_name); return base.is_valid() && base->var_map.has(p_name);
} }
bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_property) const { bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_property) const {
if (base->data.has(p_name)) { if (base->var_map.has(p_name)) {
r_property = base->data[p_name].get_value(); r_property = base->var_map[p_name].get_value();
return true; return true;
} }
return false; return false;
@ -115,54 +115,44 @@ void BlackboardPlan::set_base_plan(const Ref<BlackboardPlan> &p_base) {
} }
void BlackboardPlan::add_var(const String &p_name, const BBVariable &p_var) { void BlackboardPlan::add_var(const String &p_name, const BBVariable &p_var) {
ERR_FAIL_COND(data.has(p_name)); ERR_FAIL_COND(var_map.has(p_name));
ERR_FAIL_COND(base.is_valid()); var_map.insert(p_name, p_var);
data.insert(p_name, p_var); var_list.push_back(Pair<String, BBVariable>(p_name, p_var));
notify_property_list_changed(); notify_property_list_changed();
emit_changed(); emit_changed();
} }
void BlackboardPlan::remove_var(const String &p_name) { void BlackboardPlan::remove_var(const String &p_name) {
ERR_FAIL_COND(!data.has(p_name)); ERR_FAIL_COND(!var_map.has(p_name));
ERR_FAIL_COND(base.is_valid()); var_list.erase(Pair<String, BBVariable>(p_name, var_map[p_name]));
data.erase(p_name); var_map.erase(p_name);
notify_property_list_changed(); notify_property_list_changed();
emit_changed(); emit_changed();
} }
BBVariable BlackboardPlan::get_var(const String &p_name) { BBVariable BlackboardPlan::get_var(const String &p_name) {
ERR_FAIL_COND_V(!data.has(p_name), BBVariable()); ERR_FAIL_COND_V(!var_map.has(p_name), BBVariable());
return data.get(p_name); return var_map.get(p_name);
} }
Pair<String, BBVariable> BlackboardPlan::get_var_by_index(int p_index) { Pair<String, BBVariable> BlackboardPlan::get_var_by_index(int p_index) {
Pair<String, BBVariable> ret; Pair<String, BBVariable> ret;
ERR_FAIL_INDEX_V(p_index, (int)data.size(), ret); ERR_FAIL_INDEX_V(p_index, (int)var_map.size(), ret);
return var_list[p_index];
int i = 0;
for (const KeyValue<String, BBVariable> &kv : data) {
if (i == p_index) {
ret.first = kv.key;
ret.second = kv.value;
}
i += 1;
}
return ret;
} }
PackedStringArray BlackboardPlan::list_vars() const { PackedStringArray BlackboardPlan::list_vars() const {
PackedStringArray ret; PackedStringArray ret;
for (const KeyValue<String, BBVariable> &kv : data) { for (const Pair<String, BBVariable> &p : var_list) {
ret.append(kv.key); ret.append(p.first);
} }
return ret; return ret;
} }
String BlackboardPlan::get_var_name(const BBVariable &p_var) const { String BlackboardPlan::get_var_name(const BBVariable &p_var) const {
for (const KeyValue<String, BBVariable> &kv : data) { for (const Pair<String, BBVariable> &p : var_list) {
if (kv.value == p_var) { if (p.second == p_var) {
return kv.key; return p.first;
} }
} }
return String(); return String();
@ -170,27 +160,29 @@ String BlackboardPlan::get_var_name(const BBVariable &p_var) const {
void BlackboardPlan::rename_var(const String &p_name, const String &p_new_name) { void BlackboardPlan::rename_var(const String &p_name, const String &p_new_name) {
ERR_FAIL_COND(p_new_name.is_empty()); ERR_FAIL_COND(p_new_name.is_empty());
ERR_FAIL_COND(data.has(p_new_name)); ERR_FAIL_COND(var_map.has(p_new_name));
ERR_FAIL_COND(!data.has(p_name)); ERR_FAIL_COND(!var_map.has(p_name));
BBVariable var = var_map[p_name];
Pair<String, BBVariable> new_entry(p_new_name, var);
Pair<String, BBVariable> old_entry(p_name, var);
var_list.find(old_entry)->set(new_entry);
var_map.erase(p_name);
var_map.insert(p_new_name, var);
data.replace_key(p_name, p_new_name);
notify_property_list_changed(); notify_property_list_changed();
emit_changed(); emit_changed();
} }
void BlackboardPlan::swap_vars(int p_idx_a, int p_idx_b) { void BlackboardPlan::swap_vars(int p_idx_a, int p_idx_b) {
ERR_FAIL_INDEX(p_idx_a, (int)data.size()); ERR_FAIL_INDEX(p_idx_a, (int)var_map.size());
ERR_FAIL_INDEX(p_idx_b, (int)data.size()); ERR_FAIL_INDEX(p_idx_b, (int)var_map.size());
Pair<String, BBVariable> a = get_var_by_index(p_idx_a); Pair<String, BBVariable> a = var_list[p_idx_a];
Pair<String, BBVariable> b = get_var_by_index(p_idx_b); Pair<String, BBVariable> b = var_list[p_idx_b];
data.replace_key(a.first, "__tmp__"); var_list.swap(var_list.find(a), var_list.find(b));
data.replace_key(b.first, a.first);
data.replace_key("__tmp__", b.first);
data[b.first] = b.second;
data[a.first] = a.second;
notify_property_list_changed(); notify_property_list_changed();
emit_changed(); emit_changed();
@ -204,28 +196,31 @@ void BlackboardPlan::sync_with_base_plan() {
bool changed = false; bool changed = false;
// Sync variables with the base plan. // Sync variables with the base plan.
for (const KeyValue<String, BBVariable> &kv : base->data) { for (const Pair<String, BBVariable> &p : base->var_list) {
if (!data.has(kv.key)) { const String &base_name = p.first;
data.insert(kv.key, kv.value.duplicate()); const BBVariable &base_var = p.second;
if (!var_map.has(base_name)) {
add_var(base_name, base_var.duplicate());
changed = true; changed = true;
continue; continue;
} }
BBVariable var = data.get(kv.key); BBVariable var = var_map[base_name];
if (!var.is_same_prop_info(kv.value)) { if (!var.is_same_prop_info(base_var)) {
var.copy_prop_info(kv.value); var.copy_prop_info(base_var);
changed = true; changed = true;
} }
if (var.get_value().get_type() != kv.value.get_type()) { if (var.get_value().get_type() != base_var.get_type()) {
var.set_value(kv.value.get_value()); var.set_value(base_var.get_value());
changed = true; changed = true;
} }
} }
// Erase variables that do not exist in the base plan. // Erase variables that do not exist in the base plan.
for (const KeyValue<String, BBVariable> &kv : data) { for (const Pair<String, BBVariable> &p : var_list) {
if (!base->data.has(kv.key)) { if (!base->has_var(p.first)) {
data.erase(kv.key); remove_var(p.first);
changed = true; changed = true;
} }
} }
@ -238,22 +233,22 @@ void BlackboardPlan::sync_with_base_plan() {
Ref<Blackboard> BlackboardPlan::create_blackboard() { Ref<Blackboard> BlackboardPlan::create_blackboard() {
Ref<Blackboard> bb = memnew(Blackboard); Ref<Blackboard> bb = memnew(Blackboard);
for (const KeyValue<String, BBVariable> &kv : data) { for (const Pair<String, BBVariable> &p : var_list) {
bb->add_var(kv.key, kv.value.duplicate()); bb->add_var(p.first, p.second.duplicate());
} }
return bb; return bb;
} }
void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite) { void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite) {
for (const KeyValue<String, BBVariable> &kv : data) { for (const Pair<String, BBVariable> &p : var_list) {
if (p_blackboard->has_var(kv.key)) { if (p_blackboard->has_var(p.first)) {
if (overwrite) { if (overwrite) {
p_blackboard->erase_var(kv.key); p_blackboard->erase_var(p.first);
} else { } else {
continue; continue;
} }
} }
p_blackboard->add_var(kv.key, kv.value.duplicate()); p_blackboard->add_var(p.first, p.second.duplicate());
} }
} }

View File

@ -12,16 +12,24 @@
#ifndef BLACKBOARD_PLAN_H #ifndef BLACKBOARD_PLAN_H
#define BLACKBOARD_PLAN_H #define BLACKBOARD_PLAN_H
#include "core/io/resource.h"
#include "bb_variable.h" #include "bb_variable.h"
#include "blackboard.h" #include "blackboard.h"
#ifdef LIMBOAI_MODULE
#include "core/io/resource.h"
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/resource.hpp>
using namespace godot;
#endif // LIMBOAI_GDEXTENSION
class BlackboardPlan : public Resource { class BlackboardPlan : public Resource {
GDCLASS(BlackboardPlan, Resource); GDCLASS(BlackboardPlan, Resource);
private: private:
HashMap<String, BBVariable> data; List<Pair<String, BBVariable>> var_list;
HashMap<String, BBVariable> var_map;
// When base is not null, the plan is considered to be derived from the base plan. // When base is not null, the plan is considered to be derived from the base plan.
// A derived plan can only have variables that exist in the base plan, // A derived plan can only have variables that exist in the base plan,
@ -29,6 +37,8 @@ private:
Ref<BlackboardPlan> base; Ref<BlackboardPlan> base;
protected: protected:
static void _bind_methods() {}
bool _set(const StringName &p_name, const Variant &p_value); bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const; bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const; void _get_property_list(List<PropertyInfo> *p_list) const;
@ -43,9 +53,9 @@ public:
void remove_var(const String &p_name); void remove_var(const String &p_name);
BBVariable get_var(const String &p_name); BBVariable get_var(const String &p_name);
Pair<String, BBVariable> get_var_by_index(int p_index); Pair<String, BBVariable> get_var_by_index(int p_index);
bool has_var(const String &p_name) { return data.has(p_name); } bool has_var(const String &p_name) { return var_map.has(p_name); }
bool is_empty() const { return data.is_empty(); } bool is_empty() const { return var_map.is_empty(); }
int get_var_count() const { return data.size(); } int get_var_count() const { return var_map.size(); }
PackedStringArray list_vars() const; PackedStringArray list_vars() const;
String get_var_name(const BBVariable &p_var) const; String get_var_name(const BBVariable &p_var) const;

View File

@ -11,6 +11,7 @@
#include "blackboard_plan_editor.h" #include "blackboard_plan_editor.h"
#include "../util/limbo_compat.h"
#include "../util/limbo_string_names.h" #include "../util/limbo_string_names.h"
#include "../util/limbo_utility.h" #include "../util/limbo_utility.h"
@ -22,6 +23,19 @@
#include "scene/resources/style_box_flat.h" #include "scene/resources/style_box_flat.h"
#endif // LIMBOAI_MODULE #endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/editor_interface.hpp>
#include <godot_cpp/classes/h_box_container.hpp>
#include <godot_cpp/classes/input.hpp>
#include <godot_cpp/classes/input_event_mouse_motion.hpp>
#include <godot_cpp/classes/label.hpp>
#include <godot_cpp/classes/line_edit.hpp>
#include <godot_cpp/classes/margin_container.hpp>
#include <godot_cpp/classes/theme.hpp>
using namespace godot;
#endif // LIMBOAI_GDEXTENSION
void BlackboardPlanEditor::_add_var() { void BlackboardPlanEditor::_add_var() {
ERR_FAIL_NULL(plan); ERR_FAIL_NULL(plan);
@ -78,7 +92,8 @@ void BlackboardPlanEditor::_show_button_popup(Button *p_button, PopupMenu *p_pop
ERR_FAIL_NULL(p_button); ERR_FAIL_NULL(p_button);
ERR_FAIL_NULL(p_popup); ERR_FAIL_NULL(p_popup);
Rect2 rect = p_button->get_screen_rect(); Transform2D xform = p_button->get_screen_transform();
Rect2 rect(xform.get_origin(), xform.get_scale() * p_button->get_size());
rect.position.y += rect.size.height; rect.position.y += rect.size.height;
rect.size.height = 0; rect.size.height = 0;
p_popup->set_size(rect.size); p_popup->set_size(rect.size);
@ -137,8 +152,8 @@ void BlackboardPlanEditor::_drag_button_gui_input(const Ref<InputEvent> &p_event
ERR_FAIL_NULL(row); ERR_FAIL_NULL(row);
ERR_FAIL_NULL(other_row); ERR_FAIL_NULL(other_row);
rows_vbox->move_child(row, drag_index + drag_dir); rows_vbox->move_child(row, drag_index + drag_dir);
row->add_theme_style_override(LW_NAME(panel), row->get_index() % 2 ? theme_cache.odd_style : theme_cache.even_style); ADD_STYLEBOX_OVERRIDE(row, LW_NAME(panel), row->get_index() % 2 ? theme_cache.odd_style : theme_cache.even_style);
other_row->add_theme_style_override(LW_NAME(panel), other_row->get_index() % 2 ? theme_cache.odd_style : theme_cache.even_style); ADD_STYLEBOX_OVERRIDE(other_row, LW_NAME(panel), other_row->get_index() % 2 ? theme_cache.odd_style : theme_cache.even_style);
drag_index += drag_dir; drag_index += drag_dir;
} }
@ -167,7 +182,7 @@ void BlackboardPlanEditor::_refresh() {
PanelContainer *row_panel = memnew(PanelContainer); PanelContainer *row_panel = memnew(PanelContainer);
rows_vbox->add_child(row_panel); rows_vbox->add_child(row_panel);
row_panel->add_theme_style_override(LW_NAME(panel), idx % 2 ? theme_cache.odd_style : theme_cache.even_style); ADD_STYLEBOX_OVERRIDE(row_panel, LW_NAME(panel), idx % 2 ? theme_cache.odd_style : theme_cache.even_style);
row_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL); row_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
HBoxContainer *props_hbox = memnew(HBoxContainer); HBoxContainer *props_hbox = memnew(HBoxContainer);
@ -177,7 +192,7 @@ void BlackboardPlanEditor::_refresh() {
Button *drag_button = memnew(Button); Button *drag_button = memnew(Button);
props_hbox->add_child(drag_button); props_hbox->add_child(drag_button);
drag_button->set_custom_minimum_size(Size2(28.0, 28.0) * EDSCALE); drag_button->set_custom_minimum_size(Size2(28.0, 28.0) * EDSCALE);
drag_button->set_icon(theme_cache.grab_icon); BUTTON_SET_ICON(drag_button, theme_cache.grab_icon);
drag_button->connect(LW_NAME(gui_input), callable_mp(this, &BlackboardPlanEditor::_drag_button_gui_input)); drag_button->connect(LW_NAME(gui_input), callable_mp(this, &BlackboardPlanEditor::_drag_button_gui_input));
drag_button->connect(LW_NAME(button_down), callable_mp(this, &BlackboardPlanEditor::_drag_button_down).bind(row_panel)); drag_button->connect(LW_NAME(button_down), callable_mp(this, &BlackboardPlanEditor::_drag_button_down).bind(row_panel));
drag_button->connect(LW_NAME(button_up), callable_mp(this, &BlackboardPlanEditor::_drag_button_up)); drag_button->connect(LW_NAME(button_up), callable_mp(this, &BlackboardPlanEditor::_drag_button_up));
@ -196,7 +211,7 @@ void BlackboardPlanEditor::_refresh() {
type_choice->set_custom_minimum_size(Size2(170, 0.0) * EDSCALE); type_choice->set_custom_minimum_size(Size2(170, 0.0) * EDSCALE);
type_choice->set_text(Variant::get_type_name(var.get_type())); type_choice->set_text(Variant::get_type_name(var.get_type()));
type_choice->set_tooltip_text(Variant::get_type_name(var.get_type())); type_choice->set_tooltip_text(Variant::get_type_name(var.get_type()));
type_choice->set_icon(get_theme_icon(Variant::get_type_name(var.get_type()), LW_NAME(EditorIcons))); BUTTON_SET_ICON(type_choice, get_theme_icon(Variant::get_type_name(var.get_type()), LW_NAME(EditorIcons)));
type_choice->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); type_choice->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
type_choice->set_flat(true); type_choice->set_flat(true);
type_choice->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT); type_choice->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
@ -225,7 +240,7 @@ void BlackboardPlanEditor::_refresh() {
Button *trash_button = memnew(Button); Button *trash_button = memnew(Button);
props_hbox->add_child(trash_button); props_hbox->add_child(trash_button);
trash_button->set_custom_minimum_size(Size2(24.0, 0.0) * EDSCALE); trash_button->set_custom_minimum_size(Size2(24.0, 0.0) * EDSCALE);
trash_button->set_icon(theme_cache.trash_icon); BUTTON_SET_ICON(trash_button, theme_cache.trash_icon);
trash_button->connect(LW_NAME(pressed), callable_mp(this, &BlackboardPlanEditor::_trash_var).bind(idx)); trash_button->connect(LW_NAME(pressed), callable_mp(this, &BlackboardPlanEditor::_trash_var).bind(idx));
idx += 1; idx += 1;
@ -238,7 +253,7 @@ void BlackboardPlanEditor::_notification(int p_what) {
theme_cache.trash_icon = get_theme_icon(LW_NAME(Remove), LW_NAME(EditorIcons)); theme_cache.trash_icon = get_theme_icon(LW_NAME(Remove), LW_NAME(EditorIcons));
theme_cache.grab_icon = get_theme_icon(LW_NAME(TripleBar), LW_NAME(EditorIcons)); theme_cache.grab_icon = get_theme_icon(LW_NAME(TripleBar), LW_NAME(EditorIcons));
add_var_tool->set_icon(get_theme_icon(LW_NAME(Add), LW_NAME(EditorIcons))); BUTTON_SET_ICON(add_var_tool, get_theme_icon(LW_NAME(Add), LW_NAME(EditorIcons)));
type_menu->clear(); type_menu->clear();
for (int i = 0; i < Variant::VARIANT_MAX; i++) { for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@ -249,18 +264,20 @@ void BlackboardPlanEditor::_notification(int p_what) {
type_menu->add_icon_item(get_theme_icon(type, LW_NAME(EditorIcons)), type, i); type_menu->add_icon_item(get_theme_icon(type, LW_NAME(EditorIcons)), type, i);
} }
scroll_container->add_theme_style_override(LW_NAME(panel), get_theme_stylebox(LW_NAME(panel), LW_NAME(Tree))); ADD_STYLEBOX_OVERRIDE(scroll_container, LW_NAME(panel), get_theme_stylebox(LW_NAME(panel), LW_NAME(Tree)));
Color bg_color = get_theme_color(LW_NAME(dark_color_2), LW_NAME(Editor)); Color bg_color = get_theme_color(LW_NAME(dark_color_2), LW_NAME(Editor));
theme_cache.odd_style->set_bg_color(bg_color.darkened(-0.05)); theme_cache.odd_style->set_bg_color(bg_color.darkened(-0.05));
theme_cache.even_style->set_bg_color(bg_color.darkened(0.05)); theme_cache.even_style->set_bg_color(bg_color.darkened(0.05));
theme_cache.header_style->set_bg_color(bg_color.darkened(-0.2)); theme_cache.header_style->set_bg_color(bg_color.darkened(-0.2));
header_row->add_theme_style_override(LW_NAME(panel), theme_cache.header_style); ADD_STYLEBOX_OVERRIDE(header_row, LW_NAME(panel), theme_cache.header_style);
} break; } break;
case NOTIFICATION_READY: { case NOTIFICATION_READY: {
add_var_tool->connect(LW_NAME(pressed), callable_mp(this, &BlackboardPlanEditor::_add_var)); add_var_tool->connect(LW_NAME(pressed), callable_mp(this, &BlackboardPlanEditor::_add_var));
connect(LW_NAME(visibility_changed), callable_mp(this, &BlackboardPlanEditor::_visibility_changed)); connect(LW_NAME(visibility_changed), callable_mp(this, &BlackboardPlanEditor::_visibility_changed));
type_menu->connect(LW_NAME(id_pressed), callable_mp(this, &BlackboardPlanEditor::_type_chosen));
hint_menu->connect(LW_NAME(id_pressed), callable_mp(this, &BlackboardPlanEditor::_hint_chosen));
} break; } break;
} }
} }
@ -338,11 +355,9 @@ BlackboardPlanEditor::BlackboardPlanEditor() {
type_menu = memnew(PopupMenu); type_menu = memnew(PopupMenu);
add_child(type_menu); add_child(type_menu);
type_menu->connect(LW_NAME(id_pressed), callable_mp(this, &BlackboardPlanEditor::_type_chosen));
hint_menu = memnew(PopupMenu); hint_menu = memnew(PopupMenu);
add_child(hint_menu); add_child(hint_menu);
hint_menu->connect(LW_NAME(id_pressed), callable_mp(this, &BlackboardPlanEditor::_hint_chosen));
for (int i = 0; i < PropertyHint::PROPERTY_HINT_MAX; i++) { for (int i = 0; i < PropertyHint::PROPERTY_HINT_MAX; i++) {
hint_menu->add_item(LimboUtility::get_singleton()->get_property_hint_text(PropertyHint(i)), i); hint_menu->add_item(LimboUtility::get_singleton()->get_property_hint_text(PropertyHint(i)), i);
} }
@ -352,7 +367,7 @@ BlackboardPlanEditor::BlackboardPlanEditor() {
theme_cache.header_style.instantiate(); theme_cache.header_style.instantiate();
} }
// ***** // ***** EditorInspectorPluginBBPlan *****
void EditorInspectorPluginBBPlan::_edit_plan(const Ref<BlackboardPlan> &p_plan) { void EditorInspectorPluginBBPlan::_edit_plan(const Ref<BlackboardPlan> &p_plan) {
ERR_FAIL_NULL(p_plan); ERR_FAIL_NULL(p_plan);
@ -366,7 +381,11 @@ void EditorInspectorPluginBBPlan::_open_base_plan(const Ref<BlackboardPlan> &p_p
EditorInterface::get_singleton()->call_deferred("edit_resource", p_plan->get_base_plan()); EditorInterface::get_singleton()->call_deferred("edit_resource", p_plan->get_base_plan());
} }
#ifdef LIMBOAI_MODULE
bool EditorInspectorPluginBBPlan::can_handle(Object *p_object) { bool EditorInspectorPluginBBPlan::can_handle(Object *p_object) {
#elif LIMBOAI_GDEXTENSION
bool EditorInspectorPluginBBPlan::_can_handle(Object *p_object) const {
#endif
Ref<BlackboardPlan> plan = Object::cast_to<BlackboardPlan>(p_object); Ref<BlackboardPlan> plan = Object::cast_to<BlackboardPlan>(p_object);
if (plan.is_valid()) { if (plan.is_valid()) {
plan->sync_with_base_plan(); plan->sync_with_base_plan();
@ -374,12 +393,16 @@ bool EditorInspectorPluginBBPlan::can_handle(Object *p_object) {
return plan.is_valid(); return plan.is_valid();
} }
#ifdef LIMBOAI_MODULE
void EditorInspectorPluginBBPlan::parse_begin(Object *p_object) { void EditorInspectorPluginBBPlan::parse_begin(Object *p_object) {
#elif LIMBOAI_GDEXTENSION
void EditorInspectorPluginBBPlan::_parse_begin(Object *p_object) {
#endif
Ref<BlackboardPlan> plan = Object::cast_to<BlackboardPlan>(p_object); Ref<BlackboardPlan> plan = Object::cast_to<BlackboardPlan>(p_object);
ERR_FAIL_NULL(plan); ERR_FAIL_NULL(plan);
PanelContainer *panel = memnew(PanelContainer); PanelContainer *panel = memnew(PanelContainer);
panel->add_theme_style_override(LW_NAME(panel), toolbar_style); ADD_STYLEBOX_OVERRIDE(panel, LW_NAME(panel), toolbar_style);
MarginContainer *margin_container = memnew(MarginContainer); MarginContainer *margin_container = memnew(MarginContainer);
panel->add_child(margin_container); panel->add_child(margin_container);

View File

@ -19,6 +19,17 @@
#include "scene/gui/dialogs.h" #include "scene/gui/dialogs.h"
#endif // LIMBOAI_MODULE #endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/accept_dialog.hpp>
#include <godot_cpp/classes/editor_inspector_plugin.hpp>
#include <godot_cpp/classes/panel_container.hpp>
#include <godot_cpp/classes/popup_menu.hpp>
#include <godot_cpp/classes/scroll_container.hpp>
#include <godot_cpp/classes/style_box_flat.hpp>
#include <godot_cpp/classes/v_box_container.hpp>
using namespace godot;
#endif // LIMBOAI_GDEXTENSION
// ***** // *****
class BlackboardPlanEditor : public AcceptDialog { class BlackboardPlanEditor : public AcceptDialog {
@ -65,6 +76,8 @@ private:
void _visibility_changed(); void _visibility_changed();
protected: protected:
static void _bind_methods() {}
void _notification(int p_what); void _notification(int p_what);
public: public:
@ -85,9 +98,17 @@ private:
void _edit_plan(const Ref<BlackboardPlan> &p_plan); void _edit_plan(const Ref<BlackboardPlan> &p_plan);
void _open_base_plan(const Ref<BlackboardPlan> &p_plan); void _open_base_plan(const Ref<BlackboardPlan> &p_plan);
protected:
static void _bind_methods() {}
public: public:
#ifdef LIMBOAI_MODULE
virtual bool can_handle(Object *p_object) override; virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override; virtual void parse_begin(Object *p_object) override;
#elif LIMBOAI_GDEXTENSION
virtual bool _can_handle(Object *p_object) const override;
virtual void _parse_begin(Object *p_object) override;
#endif
EditorInspectorPluginBBPlan(); EditorInspectorPluginBBPlan();
}; };

View File

@ -1394,6 +1394,11 @@ void LimboAIEditorPlugin::_notification(int p_notification) {
switch (p_notification) { switch (p_notification) {
case NOTIFICATION_READY: { case NOTIFICATION_READY: {
add_debugger_plugin(memnew(LimboDebuggerPlugin)); add_debugger_plugin(memnew(LimboDebuggerPlugin));
add_inspector_plugin(memnew(EditorInspectorPluginBBPlan));
#ifdef LIMBOAI_MODULE
// ! Only used in the module version.
add_inspector_plugin(memnew(EditorInspectorPluginBBParam));
#endif // LIMBOAI_MODULE
} break; } break;
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
// Add BehaviorTree to the list of resources that should open in a new inspector. // Add BehaviorTree to the list of resources that should open in a new inspector.
@ -1447,12 +1452,6 @@ LimboAIEditorPlugin::LimboAIEditorPlugin() {
MAIN_SCREEN_CONTROL()->add_child(limbo_ai_editor); MAIN_SCREEN_CONTROL()->add_child(limbo_ai_editor);
limbo_ai_editor->hide(); limbo_ai_editor->hide();
limbo_ai_editor->set_plugin(this); limbo_ai_editor->set_plugin(this);
add_inspector_plugin(memnew(EditorInspectorPluginBBPlan));
#ifdef LIMBOAI_MODULE
// ! Only used in the module version.
add_inspector_plugin(memnew(EditorInspectorPluginBBParam));
#endif // LIMBOAI_MODULE
} }
LimboAIEditorPlugin::~LimboAIEditorPlugin() { LimboAIEditorPlugin::~LimboAIEditorPlugin() {

View File

@ -95,6 +95,7 @@
#include "bt/tasks/utility/bt_wait.h" #include "bt/tasks/utility/bt_wait.h"
#include "bt/tasks/utility/bt_wait_ticks.h" #include "bt/tasks/utility/bt_wait_ticks.h"
#include "editor/action_banner.h" #include "editor/action_banner.h"
#include "editor/blackboard_plan_editor.h"
#include "editor/debugger/behavior_tree_data.h" #include "editor/debugger/behavior_tree_data.h"
#include "editor/debugger/limbo_debugger.h" #include "editor/debugger/limbo_debugger.h"
#include "editor/debugger/limbo_debugger_plugin.h" #include "editor/debugger/limbo_debugger_plugin.h"
@ -253,6 +254,8 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(BehaviorTreeView); GDREGISTER_CLASS(BehaviorTreeView);
GDREGISTER_CLASS(LimboDebuggerTab); GDREGISTER_CLASS(LimboDebuggerTab);
GDREGISTER_CLASS(LimboDebuggerPlugin); GDREGISTER_CLASS(LimboDebuggerPlugin);
GDREGISTER_CLASS(BlackboardPlanEditor);
GDREGISTER_CLASS(EditorInspectorPluginBBPlan);
GDREGISTER_CLASS(LimboAIEditor); GDREGISTER_CLASS(LimboAIEditor);
GDREGISTER_CLASS(LimboAIEditorPlugin); GDREGISTER_CLASS(LimboAIEditorPlugin);
#endif // LIMBOAI_GDEXTENSION #endif // LIMBOAI_GDEXTENSION

View File

@ -52,6 +52,7 @@
#define DIR_ACCESS_CREATE() DirAccess::create(DirAccess::ACCESS_RESOURCES) #define DIR_ACCESS_CREATE() DirAccess::create(DirAccess::ACCESS_RESOURCES)
#define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable, Variant())) #define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable, Variant()))
#define GET_SCRIPT(m_obj) (m_obj->get_script_instance() ? m_obj->get_script_instance()->get_script() : nullptr) #define GET_SCRIPT(m_obj) (m_obj->get_script_instance() ? m_obj->get_script_instance()->get_script() : nullptr)
#define ADD_STYLEBOX_OVERRIDE(m_control, m_name, m_stylebox) (m_control->add_theme_style_override(m_name, m_stylebox))
#define VARIANT_EVALUATE(m_op, m_lvalue, m_rvalue, r_ret) r_ret = Variant::evaluate(m_op, m_lvalue, m_rvalue) #define VARIANT_EVALUATE(m_op, m_lvalue, m_rvalue, r_ret) r_ret = Variant::evaluate(m_op, m_lvalue, m_rvalue)
@ -130,6 +131,7 @@ using namespace godot;
#define DIR_ACCESS_CREATE() DirAccess::open("res://") #define DIR_ACCESS_CREATE() DirAccess::open("res://")
#define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable)) #define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable))
#define GET_SCRIPT(m_obj) (m_obj->get_script()) #define GET_SCRIPT(m_obj) (m_obj->get_script())
#define ADD_STYLEBOX_OVERRIDE(m_control, m_name, m_stylebox) (m_control->add_theme_stylebox_override(m_name, m_stylebox))
#define VARIANT_EVALUATE(m_op, m_lvalue, m_rvalue, r_ret) \ #define VARIANT_EVALUATE(m_op, m_lvalue, m_rvalue, r_ret) \
{ \ { \