Implement mode switch button for BB parameters

This commit is contained in:
Serhii Snitsaruk 2023-12-09 19:31:51 +01:00
parent b4bef31df5
commit 91ed8bfe3d
4 changed files with 150 additions and 31 deletions

View File

@ -12,6 +12,7 @@
#include "editor_property_bb_param.h" #include "editor_property_bb_param.h"
#include "modules/limboai/blackboard/bb_param/bb_param.h" #include "modules/limboai/blackboard/bb_param/bb_param.h"
#include "modules/limboai/editor/mode_switch_button.h"
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/object/class_db.h" #include "core/object/class_db.h"
@ -204,7 +205,7 @@ void EditorPropertyBBParam::_value_edited(const String &p_property, Variant p_va
} }
void EditorPropertyBBParam::_mode_changed() { void EditorPropertyBBParam::_mode_changed() {
_get_edited_param()->set_value_source(value_mode->is_pressed() ? BBParam::SAVED_VALUE : BBParam::BLACKBOARD_VAR); _get_edited_param()->set_value_source(mode_button->get_mode() == Mode::SPECIFY_VALUE ? BBParam::SAVED_VALUE : BBParam::BLACKBOARD_VAR);
update_property(); update_property();
} }
@ -219,15 +220,13 @@ void EditorPropertyBBParam::update_property() {
variable_edit->set_text(param->get_variable()); variable_edit->set_text(param->get_variable());
variable_edit->set_editable(true); variable_edit->set_editable(true);
variable_edit->show(); variable_edit->show();
variable_mode->set_pressed_no_signal(true); mode_button->set_mode(Mode::BIND_VAR, true);
value_mode->set_pressed_no_signal(false);
} else { } else {
variable_edit->hide(); variable_edit->hide();
_create_value_editor(param->get_type()); _create_value_editor(param->get_type());
value_editor->show(); value_editor->show();
value_editor->set_object_and_property(param.ptr(), SNAME("saved_value")); value_editor->set_object_and_property(param.ptr(), SNAME("saved_value"));
value_mode->set_pressed_no_signal(true); mode_button->set_mode(Mode::SPECIFY_VALUE, true);
variable_mode->set_pressed_no_signal(false);
value_editor->update_property(); value_editor->update_property();
} }
} }
@ -241,8 +240,13 @@ void EditorPropertyBBParam::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_ENTER_TREE: case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: { case NOTIFICATION_THEME_CHANGED: {
value_mode->set_icon(get_editor_theme_icon(SNAME("LimboSpecifyValue"))); int id = mode_button->get_mode();
variable_mode->set_icon(get_editor_theme_icon(SNAME("BTSetVar"))); mode_button->clear();
mode_button->add_mode(Mode::SPECIFY_VALUE, get_editor_theme_icon(SNAME("LimboSpecifyValue")), TTR("Mode: Specify value.\nClick to switch mode."));
mode_button->add_mode(Mode::BIND_VAR, get_editor_theme_icon(SNAME("BTSetVar")), TTR("Mode: Bind blackboard variable.\nClick to switch mode."));
if (id >= 0) {
mode_button->set_mode(id);
}
} break; } break;
} }
} }
@ -251,28 +255,10 @@ EditorPropertyBBParam::EditorPropertyBBParam() {
hbox = memnew(HBoxContainer); hbox = memnew(HBoxContainer);
add_child(hbox); add_child(hbox);
HBoxContainer *modes = memnew(HBoxContainer); mode_button = memnew(ModeSwitchButton);
hbox->add_child(modes); hbox->add_child(mode_button);
modes->add_theme_constant_override("separation", 0); mode_button->set_focus_mode(FOCUS_NONE);
mode_button->connect(SNAME("mode_changed"), callable_mp(this, &EditorPropertyBBParam::_mode_changed));
Ref<ButtonGroup> modes_group;
modes_group.instantiate();
value_mode = memnew(Button);
modes->add_child(value_mode);
value_mode->set_focus_mode(FOCUS_NONE);
value_mode->set_button_group(modes_group);
value_mode->set_toggle_mode(true);
value_mode->set_tooltip_text(TTR("Specify value"));
value_mode->connect(SNAME("pressed"), callable_mp(this, &EditorPropertyBBParam::_mode_changed));
variable_mode = memnew(Button);
modes->add_child(variable_mode);
variable_mode->set_focus_mode(FOCUS_NONE);
variable_mode->set_button_group(modes_group);
variable_mode->set_toggle_mode(true);
variable_mode->set_tooltip_text(TTR("Bind to a blackboard variable"));
variable_mode->connect(SNAME("pressed"), callable_mp(this, &EditorPropertyBBParam::_mode_changed));
variable_edit = memnew(LineEdit); variable_edit = memnew(LineEdit);
hbox->add_child(variable_edit); hbox->add_child(variable_edit);

View File

@ -16,17 +16,23 @@
#include "editor/editor_inspector.h" #include "editor/editor_inspector.h"
#include "modules/limboai/blackboard/bb_param/bb_param.h" #include "modules/limboai/blackboard/bb_param/bb_param.h"
#include "modules/limboai/editor/mode_switch_button.h"
class EditorPropertyBBParam : public EditorProperty { class EditorPropertyBBParam : public EditorProperty {
GDCLASS(EditorPropertyBBParam, EditorProperty); GDCLASS(EditorPropertyBBParam, EditorProperty);
private: private:
enum Mode {
SPECIFY_VALUE,
BIND_VAR,
};
StringName param_type; StringName param_type;
PropertyHint property_hint = PROPERTY_HINT_NONE; PropertyHint property_hint = PROPERTY_HINT_NONE;
Mode mode = Mode::SPECIFY_VALUE;
HBoxContainer *hbox = nullptr; HBoxContainer *hbox = nullptr;
Button *value_mode = nullptr; ModeSwitchButton *mode_button = nullptr;
Button *variable_mode = nullptr;
EditorProperty *value_editor = nullptr; EditorProperty *value_editor = nullptr;
LineEdit *variable_edit = nullptr; LineEdit *variable_edit = nullptr;

View File

@ -0,0 +1,73 @@
/**
* mode_switch_button.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 "mode_switch_button.h"
#include "core/error/error_macros.h"
#include "core/object/object.h"
#include "core/variant/variant.h"
void ModeSwitchButton::add_mode(int p_id, const Ref<Texture2D> &p_icon, const String &p_tooltip) {
bool unique_id = true;
for (int i = 0; i < modes.size(); i++) {
if (modes[i].id == p_id) {
unique_id = false;
break;
}
}
ERR_FAIL_COND_MSG(unique_id == false, "ID is already in use by another button state: " + itos(p_id));
Mode mode;
mode.id = p_id;
mode.icon = p_icon;
mode.tooltip = p_tooltip;
modes.append(mode);
if (current_mode_index == -1) {
_set_mode(0);
}
}
void ModeSwitchButton::set_mode(int p_id, bool p_no_signal) {
ERR_FAIL_COND_MSG(modes.is_empty(), "Cannot set button state with zero states.");
int idx = -1;
for (int i = 0; i < modes.size(); i++) {
if (modes[i].id == p_id) {
idx = i;
break;
}
}
ERR_FAIL_COND_MSG(idx == -1, "Button state not found with such id: " + itos(p_id));
_set_mode(p_id);
if (!p_no_signal) {
emit_signal(SNAME("mode_changed"));
}
}
void ModeSwitchButton::clear() {
current_mode_index = -1;
modes.clear();
}
void ModeSwitchButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_mode", "p_id", "p_icon", "p_tooltip"), &ModeSwitchButton::add_mode);
ClassDB::bind_method(D_METHOD("get_mode"), &ModeSwitchButton::get_mode);
ClassDB::bind_method(D_METHOD("set_mode", "p_id"), &ModeSwitchButton::set_mode);
ClassDB::bind_method(D_METHOD("next_mode"), &ModeSwitchButton::next_mode);
ADD_SIGNAL(MethodInfo("mode_changed"));
}
ModeSwitchButton::ModeSwitchButton() {
call_deferred(SNAME("connect"), SNAME("pressed"), callable_mp(this, &ModeSwitchButton::next_mode));
}

View File

@ -0,0 +1,54 @@
/**
* mode_switch_button.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 MODE_SWITCH_BUTTON
#define MODE_SWITCH_BUTTON
#include "scene/gui/button.h"
#include "core/typedefs.h"
#include "scene/resources/texture.h"
class ModeSwitchButton : public Button {
GDCLASS(ModeSwitchButton, Button);
private:
struct Mode {
int id = 0;
Ref<Texture2D> icon = nullptr;
String tooltip = "";
};
int current_mode_index = -1;
Vector<Mode> modes;
_FORCE_INLINE_ void _set_mode(int p_id) {
current_mode_index = p_id;
set_icon(modes[current_mode_index].icon);
if (!modes[current_mode_index].tooltip.is_empty()) {
set_tooltip_text(modes[current_mode_index].tooltip);
}
}
protected:
static void _bind_methods();
public:
void add_mode(int p_id, const Ref<Texture2D> &p_icon, const String &p_tooltip = "");
int get_mode() const { return modes.size() > 0 ? modes[current_mode_index].id : -1; }
void set_mode(int p_id, bool p_no_signal = false);
_FORCE_INLINE_ void next_mode() { set_mode((current_mode_index + 1) % modes.size()); };
void clear();
ModeSwitchButton();
};
#endif // MODE_SWITCH_BUTTON