Refactor HSM to use StringName for events

This commit is contained in:
Serhii Snitsaruk 2024-03-04 15:53:39 +01:00
parent 84aeb4bfff
commit 88df78c4a2
8 changed files with 48 additions and 43 deletions

View File

@ -1,7 +1,7 @@
/** /**
* bt_state.cpp * bt_state.cpp
* ============================================================================= * =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk * Copyright 2021-2024 Serhii Snitsaruk
* *
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
@ -113,11 +113,11 @@ void BTState::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_failure_event"), &BTState::get_failure_event); ClassDB::bind_method(D_METHOD("get_failure_event"), &BTState::get_failure_event);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "success_event"), "set_success_event", "get_success_event"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "success_event"), "set_success_event", "get_success_event");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "failure_event"), "set_failure_event", "get_failure_event"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "failure_event"), "set_failure_event", "get_failure_event");
} }
BTState::BTState() { BTState::BTState() {
success_event = "success"; success_event = LW_NAME(EVENT_SUCCESS);
failure_event = "failure"; failure_event = LW_NAME(EVENT_FAILURE);
} }

View File

@ -1,7 +1,7 @@
/** /**
* bt_state.h * bt_state.h
* ============================================================================= * =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk * Copyright 2021-2024 Serhii Snitsaruk
* *
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
@ -23,14 +23,16 @@ class BTState : public LimboState {
private: private:
Ref<BehaviorTree> behavior_tree; Ref<BehaviorTree> behavior_tree;
Ref<BTTask> tree_instance; Ref<BTTask> tree_instance;
String success_event; StringName success_event;
String failure_event; StringName failure_event;
void _update_blackboard_plan(); void _update_blackboard_plan();
protected: protected:
static void _bind_methods(); static void _bind_methods();
void _notification(int p_notification);
virtual void _setup() override; virtual void _setup() override;
virtual void _exit() override; virtual void _exit() override;
virtual void _update(double p_delta) override; virtual void _update(double p_delta) override;
@ -41,16 +43,13 @@ public:
Ref<BTTask> get_tree_instance() const { return tree_instance; } Ref<BTTask> get_tree_instance() const { return tree_instance; }
void set_success_event(String p_success_event) { success_event = p_success_event; } void set_success_event(const StringName &p_success_event) { success_event = p_success_event; }
String get_success_event() const { return success_event; } StringName get_success_event() const { return success_event; }
void set_failure_event(String p_failure_event) { failure_event = p_failure_event; } void set_failure_event(const StringName &p_failure_event) { failure_event = p_failure_event; }
String get_failure_event() const { return failure_event; } StringName get_failure_event() const { return failure_event; }
BTState(); BTState();
protected:
void _notification(int p_notification);
}; };
#endif // BT_STATE_H #endif // BT_STATE_H

View File

@ -1,7 +1,7 @@
/** /**
* limbo_hsm.cpp * limbo_hsm.cpp
* ============================================================================= * =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk * Copyright 2021-2024 Serhii Snitsaruk
* *
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
@ -100,11 +100,11 @@ void LimboHSM::update(double p_delta) {
_update(p_delta); _update(p_delta);
} }
void LimboHSM::add_transition(LimboState *p_from_state, LimboState *p_to_state, const String &p_event) { void LimboHSM::add_transition(LimboState *p_from_state, LimboState *p_to_state, const StringName &p_event) {
ERR_FAIL_COND_MSG(p_from_state != nullptr && p_from_state->get_parent() != this, "LimboHSM: Unable to add a transition from a state that is not an immediate child of mine."); ERR_FAIL_COND_MSG(p_from_state != nullptr && p_from_state->get_parent() != this, "LimboHSM: Unable to add a transition from a state that is not an immediate child of mine.");
ERR_FAIL_COND_MSG(p_to_state == nullptr, "LimboHSM: Unable to add a transition to a null state."); ERR_FAIL_COND_MSG(p_to_state == nullptr, "LimboHSM: Unable to add a transition to a null state.");
ERR_FAIL_COND_MSG(p_to_state->get_parent() != this, "LimboHSM: Unable to add a transition to a state that is not an immediate child of mine."); ERR_FAIL_COND_MSG(p_to_state->get_parent() != this, "LimboHSM: Unable to add a transition to a state that is not an immediate child of mine.");
ERR_FAIL_COND_MSG(p_event.is_empty(), "LimboHSM: Failed to add transition due to empty event string."); ERR_FAIL_COND_MSG(p_event == StringName(), "LimboHSM: Failed to add transition due to empty event string.");
uint64_t key = _get_transition_key(p_from_state, p_event); uint64_t key = _get_transition_key(p_from_state, p_event);
transitions[key] = Object::cast_to<LimboState>(p_to_state); transitions[key] = Object::cast_to<LimboState>(p_to_state);
@ -127,8 +127,8 @@ void LimboHSM::set_initial_state(LimboState *p_state) {
initial_state = Object::cast_to<LimboState>(p_state); initial_state = Object::cast_to<LimboState>(p_state);
} }
bool LimboHSM::_dispatch(const String &p_event, const Variant &p_cargo) { bool LimboHSM::_dispatch(const StringName &p_event, const Variant &p_cargo) {
ERR_FAIL_COND_V(p_event.is_empty(), false); ERR_FAIL_COND_V(p_event == StringName(), false);
bool event_consumed = false; bool event_consumed = false;

View File

@ -1,7 +1,7 @@
/** /**
* limbo_hsm.h * limbo_hsm.h
* ============================================================================= * =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk * Copyright 2021-2024 Serhii Snitsaruk
* *
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
@ -30,9 +30,11 @@ private:
LimboState *active_state; LimboState *active_state;
HashMap<uint64_t, LimboState *> transitions; HashMap<uint64_t, LimboState *> transitions;
_FORCE_INLINE_ uint64_t _get_transition_key(LimboState *p_from_state, const String &p_event) { _FORCE_INLINE_ uint64_t _get_transition_key(LimboState *p_from_state, const StringName &p_event) {
uint64_t key = hash_djb2_one_64(Variant::OBJECT); uint64_t key = hash_djb2_one_64(Variant::OBJECT);
key = hash_djb2_one_64(Variant(p_from_state).hash(), key); if (p_from_state != nullptr) {
key = hash_djb2_one_64(hash_one_uint64(hash_make_uint64_t(p_from_state)), key);
}
key = hash_djb2_one_64(p_event.hash(), key); key = hash_djb2_one_64(p_event.hash(), key);
return key; return key;
} }
@ -43,7 +45,7 @@ protected:
void _notification(int p_what); void _notification(int p_what);
virtual void _initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override; virtual void _initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override;
virtual bool _dispatch(const String &p_event, const Variant &p_cargo = Variant()) override; virtual bool _dispatch(const StringName &p_event, const Variant &p_cargo = Variant()) override;
virtual void _enter() override; virtual void _enter() override;
virtual void _exit() override; virtual void _exit() override;
@ -65,7 +67,7 @@ public:
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_parent_scope = nullptr); virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_parent_scope = nullptr);
void update(double p_delta); void update(double p_delta);
void add_transition(LimboState *p_from_state, LimboState *p_to_state, const String &p_event); void add_transition(LimboState *p_from_state, LimboState *p_to_state, const StringName &p_event);
LimboState *anystate() const { return nullptr; } LimboState *anystate() const { return nullptr; }
LimboHSM(); LimboHSM();

View File

@ -1,7 +1,7 @@
/** /**
* limbo_state.cpp * limbo_state.cpp
* ============================================================================= * =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk * Copyright 2021-2024 Serhii Snitsaruk
* *
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
@ -34,7 +34,7 @@ LimboState *LimboState::get_root() const {
return const_cast<LimboState *>(state); return const_cast<LimboState *>(state);
} }
LimboState *LimboState::named(String p_name) { LimboState *LimboState::named(const String &p_name) {
set_name(p_name); set_name(p_name);
return this; return this;
} }
@ -80,8 +80,8 @@ void LimboState::_initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard)
_setup(); _setup();
} }
bool LimboState::_dispatch(const String &p_event, const Variant &p_cargo) { bool LimboState::_dispatch(const StringName &p_event, const Variant &p_cargo) {
ERR_FAIL_COND_V(p_event.is_empty(), false); ERR_FAIL_COND_V(p_event == StringName(), false);
if (handlers.size() > 0 && handlers.has(p_event)) { if (handlers.size() > 0 && handlers.has(p_event)) {
Variant ret; Variant ret;
@ -120,13 +120,13 @@ bool LimboState::_dispatch(const String &p_event, const Variant &p_cargo) {
return false; return false;
} }
void LimboState::add_event_handler(const String &p_event, const Callable &p_handler) { void LimboState::add_event_handler(const StringName &p_event, const Callable &p_handler) {
ERR_FAIL_COND(p_event.is_empty()); ERR_FAIL_COND(p_event == StringName());
ERR_FAIL_COND(!p_handler.is_valid()); ERR_FAIL_COND(!p_handler.is_valid());
handlers.insert(p_event, p_handler); handlers.insert(p_event, p_handler);
} }
bool LimboState::dispatch(const String &p_event, const Variant &p_cargo) { bool LimboState::dispatch(const StringName &p_event, const Variant &p_cargo) {
return get_root()->_dispatch(p_event, p_cargo); return get_root()->_dispatch(p_event, p_cargo);
} }
@ -196,7 +196,7 @@ void LimboState::_bind_methods() {
// TODO: Registering virtual functions is not available in godot-cpp... // TODO: Registering virtual functions is not available in godot-cpp...
#endif #endif
ADD_PROPERTY(PropertyInfo(Variant::STRING, "EVENT_FINISHED", PROPERTY_HINT_NONE, "", 0), "", "event_finished"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "EVENT_FINISHED", PROPERTY_HINT_NONE, "", 0), "", "event_finished");
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");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", 0), "", "get_blackboard"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", 0), "", "get_blackboard");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT), "set_blackboard_plan", "get_blackboard_plan"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT), "set_blackboard_plan", "get_blackboard_plan");

View File

@ -1,7 +1,7 @@
/** /**
* limbo_state.h * limbo_state.h
* ============================================================================= * =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk * Copyright 2021-2024 Serhii Snitsaruk
* *
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
@ -41,7 +41,7 @@ private:
Ref<BlackboardPlan> blackboard_plan; Ref<BlackboardPlan> blackboard_plan;
Node *agent; Node *agent;
Ref<Blackboard> blackboard; Ref<Blackboard> blackboard;
HashMap<String, Callable> handlers; HashMap<StringName, Callable> handlers;
Callable guard_callable; Callable guard_callable;
protected: protected:
@ -54,7 +54,7 @@ protected:
void _notification(int p_what); void _notification(int p_what);
virtual void _initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard); virtual void _initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard);
virtual bool _dispatch(const String &p_event, const Variant &p_cargo = Variant()); virtual bool _dispatch(const StringName &p_event, const Variant &p_cargo = Variant());
virtual void _setup(); virtual void _setup();
virtual void _enter(); virtual void _enter();
@ -69,7 +69,7 @@ protected:
#endif // LIMBOAI_MODULE #endif // LIMBOAI_MODULE
public: public:
void set_blackboard_plan(const Ref<BlackboardPlan> p_plan) { blackboard_plan = p_plan; } void set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) { blackboard_plan = p_plan; }
Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; } Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
Ref<Blackboard> get_blackboard() const { return blackboard; } Ref<Blackboard> get_blackboard() const { return blackboard; }
@ -77,15 +77,15 @@ public:
Node *get_agent() const { return agent; } Node *get_agent() const { return agent; }
void set_agent(Node *p_agent) { agent = p_agent; } void set_agent(Node *p_agent) { agent = p_agent; }
LimboState *named(String p_name); LimboState *named(const String &p_name);
LimboState *call_on_enter(const Callable &p_callable); LimboState *call_on_enter(const Callable &p_callable);
LimboState *call_on_exit(const Callable &p_callable); LimboState *call_on_exit(const Callable &p_callable);
LimboState *call_on_update(const Callable &p_callable); LimboState *call_on_update(const Callable &p_callable);
void add_event_handler(const String &p_event, const Callable &p_handler); void add_event_handler(const StringName &p_event, const Callable &p_handler);
bool dispatch(const String &p_event, const Variant &p_cargo = Variant()); bool dispatch(const StringName &p_event, const Variant &p_cargo = Variant());
_FORCE_INLINE_ String event_finished() const { return LW_NAME(EVENT_FINISHED); } _FORCE_INLINE_ StringName event_finished() const { return LW_NAME(EVENT_FINISHED); }
LimboState *get_root() const; LimboState *get_root() const;
bool is_active() const { return active; } bool is_active() const { return active; }

View File

@ -78,6 +78,9 @@ LimboStringNames::LimboStringNames() {
emit_changed = SN("emit_changed"); emit_changed = SN("emit_changed");
entered = SN("entered"); entered = SN("entered");
error_value = SN("error_value"); error_value = SN("error_value");
EVENT_FAILURE = SN("failure");
EVENT_FINISHED = SN("finished");
EVENT_SUCCESS = SN("success");
exited = SN("exited"); exited = SN("exited");
favorite_tasks_changed = SN("favorite_tasks_changed"); favorite_tasks_changed = SN("favorite_tasks_changed");
Favorites = SN("Favorites"); Favorites = SN("Favorites");
@ -160,7 +163,6 @@ LimboStringNames::LimboStringNames() {
visibility_changed = SN("visibility_changed"); visibility_changed = SN("visibility_changed");
window_visibility_changed = SN("window_visibility_changed"); window_visibility_changed = SN("window_visibility_changed");
EVENT_FINISHED = "finished";
repeat_forever.parse_utf8("Repeat ∞"); repeat_forever.parse_utf8("Repeat ∞");
output_var_prefix.parse_utf8(""); output_var_prefix.parse_utf8("");
} }

View File

@ -92,6 +92,9 @@ public:
StringName emit_changed; StringName emit_changed;
StringName entered; StringName entered;
StringName error_value; StringName error_value;
StringName EVENT_FAILURE;
StringName EVENT_FINISHED;
StringName EVENT_SUCCESS;
StringName exited; StringName exited;
StringName favorite_tasks_changed; StringName favorite_tasks_changed;
StringName Favorites; StringName Favorites;
@ -175,7 +178,6 @@ public:
StringName visibility_changed; StringName visibility_changed;
StringName window_visibility_changed; StringName window_visibility_changed;
String EVENT_FINISHED;
String repeat_forever; String repeat_forever;
String output_var_prefix; String output_var_prefix;
}; };